lyn*_*don 3 c linux stack stack-memory
对于程序来说,局部变量是在堆栈中定义和分配的,但是,我只是想知道定义局部变量的顺序与使用它的顺序不同。例如,在main函数中定义了int abc,如上所述,abc是在堆栈中分配的,这意味着如果变量a位于堆栈底部,但是当变量第一次被使用时,如何将a从堆栈中弹出?或者ebp指向所有变量已存储的位置?
本质上,在函数内,局部变量存储在堆栈帧上。在堆栈帧内,变量的访问顺序可以是随机的。我会推荐阅读以下内容: 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;
}
Run Code Online (Sandbox Code Playgroud)
编译器可以生成以下代码
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
Run Code Online (Sandbox Code Playgroud)
请注意,变量a、b和c存储在位置rbp-4、rbp-8和rbp-12,因此每个变量获得 4 个字节(在我的系统中)。它是负数,因为堆栈向下增长,并且该函数的堆栈帧的开始由以下内容指示rbp。
接下来,请注意,firstc = c + 55和 thena = a + 10不执行推送或弹出操作,而只是直接访问位置,使用add DWORD PTR [rbp-12], 55和 add DWORD PTR [rbp-4], 10。编译器将知道这些变量在堆栈帧中的位置。
请注意push rbp在声明和访问变量之前。此操作将(基指针,64 位)的当前值存储rbp在堆栈帧上。接下来rbp更新以获得指示此函数限制的新值。现在在此限制内,所有局部变量都可以存储。还要注意pop rbp返回之前的情况。rbp这会从堆栈帧中恢复之前存储的旧值,以便在之后ret,它可以恢复到旧状态。