spe*_*tre 4 x86 assembly stack gcc memory-alignment
我正在玩一下以更好地掌握调用约定以及如何处理堆栈,但我无法弄清楚为什么main在设置堆栈时会分配三个额外的双字(at <main+0>).它既没有与8个字节对齐,也没有16个字节,所以这并不是我所知道的原因.正如我所看到的,main需要12个字节才能将两个参数设置为func和返回值.
我错过了什么?
该程序是在x86架构上使用"gcc -ggdb"编译的C代码.
编辑:我从gcc中删除了-O0标志,它对输出没有任何影响.
(gdb) disas main
Dump of assembler code for function main:
0x080483d1 <+0>: sub esp,0x18
0x080483d4 <+3>: mov DWORD PTR [esp+0x4],0x7
0x080483dc <+11>: mov DWORD PTR [esp],0x3
0x080483e3 <+18>: call 0x80483b4 <func>
0x080483e8 <+23>: mov DWORD PTR [esp+0x14],eax
0x080483ec <+27>: add esp,0x18
0x080483ef <+30>: ret
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
编辑:当然我应该发布C代码:
int func(int a, int b) {
int c = 9;
return a + b + c;
}
void main() {
int x;
x = func(3, 7);
}
Run Code Online (Sandbox Code Playgroud)
该平台是Arch Linux i686.
main当您输入函数时,函数的参数(包括但不限于)已经在堆栈中.您在函数内分配的空间用于局部变量.对于具有简单返回类型的函数,例如int,返回值通常位于寄存器中(eax在x86上使用典型的32位编译器).
例如,如果main是这样的话:
int main(int argc, char **argv) {
char a[35];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
...我们希望在堆栈中分配至少35个字节,因为我们输入main来腾出空间a.假设一个32位实现,通常会四舍五入到4的下一个倍数(在这种情况下为36),以保持堆栈的32位对齐.我们不希望看到为返回值分配任何空间.argc并且argv会在堆栈中,但是在main进入之前它们已经在堆栈中,因此main不必为它们分配空间.
在上面的例子中,在分配空间之后a,a将典型地开始于[esp-36],argv将处于[esp-44]并且argc将处于[esp-48](或者这两个可能是相反的 - 取决于参数是从左到右还是从右到左推).如果您想知道我为什么跳过[esp-40],那将是返回地址.
编辑:这是进入函数时堆栈的图表,并在设置堆栈帧之后:

编辑2:根据您更新的问题,您所拥有的内容略微迂回,但并不是特别难以理解.在进入时main,它不仅为本地变量分配空间main,而且还为您传递给调用函数的参数分配空间main.
这至少占了分配的一些额外空间(尽管不一定全部).
| 归档时间: |
|
| 查看次数: |
1800 次 |
| 最近记录: |