3

众所周知,当我们声明局部变量时,它们会存储到 FILO 堆栈中。但是我被要求画一个图表来显示这些变量是如何被推入堆栈的?好吧,我对给出的示例代码有点困惑:

int giveMe_Red(int *xPos, int *yPos)
{
   int count = 0;
   int *nextpos, ifTreped;
   int loc[8] = {0};
   .
   .
   .
   .
   return count;
}

任何人都可以帮助我了解每个变量是如何存储到内存中的,比如数组、指针等。比如说,0 级中的“count”,然后堆栈的 1 级中的“*nextpos”或其他内容。如果有递归,那么它们是如何存储的?

4

2 回答 2

3

细节取决于处理器,但例如在 x86 中,通常所有变量的堆栈空间都会一次分配一次,只需对esp. 标准序言是

push ebp                ; Save old base pointer
mov  ebp, esp           ; Mark current base pointer
sub  esp, stack_space   ; Allocate stack space

结语是

mov esp, ebp            ; Free stack space
pop ebp                 ; Reload old base pointer
ret                     ; Return to caller

在您的情况下,所需的空间(假设 32 位并且这些都是本地人)将是

  • 4 个字节count
  • 4 为nextPos
  • 4 为ifTreped
  • 4*8 为loc数组

总共 44 个字节(+ 4 需要保存的空间ebp)。

之后sub esp, 44会有代码将 的所有元素归零loc

编辑

在用 gcc 检查后,分配的空间似乎是 48 个字节(不是 44 个),不知道为什么,但可能是由于堆栈对齐的原因。

于 2013-09-30T06:42:33.407 回答
0

乔纳森的回答是正确的,但没有回答你的问题。所以让我们采取最简单的情况,假设没有优化,所有参数都在堆栈上传递,32 位整数,32 位地址,堆栈向下增长,调用者清理。在调用 giveme_red 之前,SP 点在某处。为了能够从调用中返回,您需要堆栈上的返回地址,即四个字节。两个 int 参数也在堆栈上,每个 4 个字节,所以 SP 现在比原来的少了 12 个字节。一旦调用 giveme_red 就需要更多空间:四个字节用于计数,四个字节用于 int 指针,另外四个用于 'iftreped',最后 8 乘以四个字节用于 int 数组。为了能够实现递归(giveme_red 直接或通过另一个函数间接调用自己),giveme_red 将需要设置一个新的堆栈帧来调用自己。重复与上述相同的顺序。通常还有一个技巧,因为您需要能够访问您的局部变量和参数,另一个称为 BP 的寄存器通常被保存和恢复(在堆栈上)。如果您想了解更多 Aho、Sethi、Ullman、Lam:编译器(The Dragon Book)仍然是标准参考。

于 2013-09-30T06:46:30.780 回答