好吧,堆栈是如何工作的?例如说明:
push ax
Run Code Online (Sandbox Code Playgroud)
等于:
sub sp, 4
mov sp, ax
Run Code Online (Sandbox Code Playgroud)
其中sp是堆栈指针.是对的吗?
我的问题是 - 如果片刻后我将其更改为完全不同的值,那么从sp寄存器中减去4是什么意思?
处理器型号 I
? Registers
? PC – Program Counter
? Single data register (accumulator) without name
? We will use symbol A to describe operations on this register
? Stack with an unspecified implementation
? Data specified by name or value
? More realistic model will follow later
Instruction Action Description
---------------------------------------------------------------------
load data A = data Load data to accumulator
store data data = A Store data from accumulator to memory
add data A += data Add data to …Run Code Online (Sandbox Code Playgroud) 假设我们有以下代码:
void foo() {
char buffer[100];
}
Run Code Online (Sandbox Code Playgroud)
在foo()返回之前,C语言中是否有一种(最好是可移植的)方式从运行时堆栈中释放缓冲区(又称添加esp,在程序集中为100 )?
c memory-management local-variables static-allocation stack-pointer
堆栈对齐在 ASMx64 中是如何工作的?什么时候需要在函数调用前对齐堆栈,需要减去多少?
我不明白这样做的目的是什么。我知道还有其他关于这个的帖子,但对我来说还不够清楚。例如:
extern foo
global bar
section .text
bar:
;some code...
sub rsp, 8 ; Why 8 (I saw this on some posts) ? Can it be another value ? Why do we need to substract?
call foo ; Do we need to align stack everytime we call a function?
add rsp, 8
;some code...
ret
Run Code Online (Sandbox Code Playgroud) assembly x86-64 calling-convention memory-alignment stack-pointer
我想知道是否有人可以向我解释汇编 ARM 中堆栈指针和帧指针之间的区别
众所周知,%rsp指向堆栈框架的顶部,%rbp指向堆栈框架的底部。然后我不明白为什么这段代码中%rbp是0x0:
(gdb) x/4xg $rsp
0x7fffffffe170: 0x00000000004000dc 0x0000000000000010
0x7fffffffe180: 0x0000000000000001 0x00007fffffffe487
(gdb) disas HelloWorldProc
Dump of assembler code for function HelloWorldProc:
=> 0x00000000004000b0 <+0>: push %rbp
0x00000000004000b1 <+1>: mov %rsp,%rbp
0x00000000004000b4 <+4>: mov $0x1,%eax
0x00000000004000b9 <+9>: mov $0x1,%edi
0x00000000004000be <+14>: movabs $0x6000ec,%rsi
0x00000000004000c8 <+24>: mov $0xd,%edx
0x00000000004000cd <+29>: syscall
0x00000000004000cf <+31>: leaveq
0x00000000004000d0 <+32>: retq
End of assembler dump.
(gdb) x/xg $rbp
0x0: Cannot access memory at address 0x0
Run Code Online (Sandbox Code Playgroud)
如果它什么都不指向,为什么为什么要“保存”(推入)%rbp?
我需要访问main函数中定义的变量a的值,而不将其作为参数传递.
main()
{
int a=10;
func();
printf("%d\n",a);
}
void func(){
//i need access of variable a here.
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
段寄存器用于将可寻址存储器的范围从 64K 字节增加到 1M 字节。但是,我很难理解堆栈段寄存器(SS),因为堆栈已经有两个与之关联的其他寄存器:sp和bp。
假设我将SS设置为5000h ,然后决定通过初始化bp和sp寄存器来初始化堆栈。最初堆栈应该是空的。因此,sp和bp最初应该具有相同的内容。我可以使用任何随机地址初始化sp吗?或者我会有一些限制吗?
例如,用地址7000h初始化sp可以吗
assembly bootloader memory-segmentation x86-16 stack-pointer
我们来看看这段代码:
A a(123);
new(&a) A(124);
Run Code Online (Sandbox Code Playgroud)
测试表明,在这种情况下,当程序关闭时,析构函数~A()将调用一次。因此,如果A我们有一些指针作为字段,我们将会出现内存泄漏。
A a(123);
a.~A();
new(&a) A(124);
Run Code Online (Sandbox Code Playgroud)
这里一切都将是正确的。但根据标准,在析构函数调用后使用对象是未定义的行为(尽管大多数编译器提供的行为没有一些问题)。
我可以获取已调用析构函数的对象的地址吗?在堆栈变量上调用放置新是正确的操作吗?
我有一个小的 C 代码,它通过修改堆栈地址处的数据来演示运行时堆栈功能。
#include <stdio.h>
int * fun() {
int a = 10;
return &a;
}
int * fun2() {
int b = 20;
return &b;
}
int main () {
int *a = fun();
int *b = fun2();
printf("a:%d b:%d\n", *a, *b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
其输出为:a:20 b:20,显示“fun2”中的“b”使用与“fun”中的“a”相同的堆栈地址。
我也想在 Rust 中测试这个。做到这一点最简单的方法是什么?
我尝试借用,但编译器说“没有借用价值”。
stack-pointer ×10
assembly ×5
c ×3
x86 ×2
x86-64 ×2
arm ×1
bootloader ×1
c++ ×1
gcc ×1
gdb ×1
linux ×1
mips ×1
new-operator ×1
rust ×1
stack ×1
stack-frame ×1
stack-memory ×1
x86-16 ×1