用例子堆叠相关问题

Stack related questions with examples

我对调用函数时堆栈外观有一些疑问,我有一些小例子可以帮助解释我的困惑:
1)
假设我们有这两个函数

int h(int k){
   k = k+3;
   return k;


int f(int x, int y){ 
   int q; 
   int z = 10; //Checkpoint_1
   q = h(x); // Checkpoint_2
   return z;

第一个问题
当我们到达Checkpoint_1行后堆栈会是什么样子,堆栈会不会有所有的本地变量(x,y,q,z)?他们在堆栈中看起来如何?

第二个问题
当我们到达 checkpoint_2 并进入函数 h(x) 并将 x+3 放入 q 后,堆栈会是什么样子,在堆栈帧中 q 会变为 x+3 吗?或者它会保持相同的 q(以 x+3 作为值)?

第三题:
这两个函数将使用哪些寄存器?我知道有一个寄存器将具有堆栈中每个帧中每个函数的 return 值(我认为它称为 %eax),但我的困惑是,假设在函数 h(int k) 中,将%eax 的值为 k 或 k+3,或者说在函数 f(int x, int y) 中 %eax 的值为 z 或 10。

非常感谢有关我的问题的任何帮助和提示。

首先我要说编译器可以自由地以某种能力做任何它想做的事——但所有现代编译器都会非常相似地做这件事。我还假设我们正在谈论 x86-64,利用 linux 上常见的 cdecl 标准。 32位不一样,Windows.

不一样

现代编译器通常在函数调用开始时为堆栈变量分配所有 space,而不考虑作用域。通常这只需 减少 rsp 中的值即可。堆栈向下增长,这意味着 减少 值与 增长 堆栈相同,因此是分配。在这种情况下,您在堆栈上初始化了两个 4 字节值,因此堆栈上将分配 8 个字节。 x 和 y 这两个变量在 64 位上将分别存储在 %rdi 和 %rsi 中。 (在 32 位上,它们存储在堆栈的 return 地址之上。)

调用h(x)后,是的,q在内存中的值会变为(x+3)。

编译器将使用它喜欢使用的任何寄存器。在这种情况下,实际上很可能 所有内容 都在寄存器中,并且除了 h 的 return 地址外根本不使用堆栈。当函数 h returns 时,k 的值(现在是 k+3)将存储在 %eax 和 returned 中。当函数freturns时,z中的值会存储在%eax和returned中。寄存器没有变量名的概念(如 z),它们只有值。编译器有责任通过将该寄存器与 z 的概念相关联来赋予这些值意义。