对于程序,局部变量是在堆栈中定义和分配的,但是,我只是想知道定义局部变量的顺序与使用它的顺序不一样。 例如,在main函数中,int a b c被定义,如上所述,b c在堆栈中分配,这意味着如果变量a位于堆栈的底部,但是当首先使用变量时,如何从堆栈弹出? 或者ebp指向所有变量已存储的位置?
答案 0 :(得分:3)
基本上在函数内,局部变量存储在堆栈帧中。在堆栈帧内,变量的访问顺序可以是随机的。我建议您阅读:http://www.cs.uwm.edu/classes/cs315/Bacon/Lecture/HTML/ch10s07.html
考虑以下代码
int main (void)
{
int a = 1, b = 2, c = 3;
c = c + 55;
a = a + 10;
return 0;
}
编译器可以生成以下代码
main:
.LFB0:
.cfi_startproc
push rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
mov rbp, rsp
.cfi_def_cfa_register 6
mov DWORD PTR [rbp-4], 1
mov DWORD PTR [rbp-8], 2
mov DWORD PTR [rbp-12], 3
add DWORD PTR [rbp-12], 55
add DWORD PTR [rbp-4], 10
mov eax, 0
pop rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
请注意,变量a
,b
和c
存储在rbp-4
,rbp-8
和rbp-12
位置,因此每个变量都会得到4个字节(在我的系统中)。它是负的,因为堆栈向下增长,此函数的堆栈帧的开始由rbp
的内容指示。
接下来,请注意,首先c = c + 55
然后a = a + 10
不执行推送或弹出操作,只需分别使用add DWORD PTR [rbp-12], 55
和add DWORD PTR [rbp-4], 10
直接访问这些位置。编译器将知道这些变量在堆栈帧中的位置。
在声明和访问变量之前请注意push rbp
。该操作将rbp
(基指针,64位)的当前值存储在堆栈帧上。更新下一个rbp
以获取指示此功能限制的新值。现在在此限制内,可以存储所有局部变量。还请注意返回前的pop rbp
。这将从之前存储的堆栈帧中恢复rbp
的旧值,以便在ret
之后,它可以返回到旧状态。