我不安静地了解gcc的序幕,特别是对于主要的。
为什么有and esp, 0xfffffff0
指令?我知道它的作用,但为什么有必要呢?
当我们调用一个函数时,我们首先必须推送参数,但是为什么gcc不使用push指令而是使用movs呢?此外,使用这些movs,它会创建一个空填充。它看起来像浪费记忆,为什么会这样?
最后,gcc首先使用子指令来esp以便为堆栈“保留”内存,但是确保其他程序不使用此内存的是什么?
我想我理解得很安静但是我找不到一个文件来解释更多关于实践中的记忆(几个程序的记忆如何重叠,......)。谢谢你的回答。
PS:我添加汇编代码和cpp代码:
Dump of assembler code for function main(int, char**):
0x08048657 <+0>: push ebp
0x08048658 <+1>: mov ebp,esp
0x0804865a <+3>: and esp,0xfffffff0
0x0804865d <+6>: sub esp,0x20
0x08048660 <+9>: mov DWORD PTR [esp+0x1c],0x3
0x08048668 <+17>: mov BYTE PTR [esp+0x1b],0x61
=> 0x0804866d <+22>: mov DWORD PTR [esp],0x8048771
0x08048674 <+29>: call 0x804863c <p(char*)>
0x08048679 <+34>: mov eax,0x0
0x0804867e <+39>: leave
0x0804867f <+40>: ret
End of assembler dump.
int main(int argc, char *argv[]) {
int b = 3;
char c = 'a';
p("hello woooooooooorld !!");}
答案 0 :(得分:3)
仅对main
进行堆栈对齐,其余函数只保留ABI所需的对齐。
编译器对本地使用mov
指令,因此可以随机访问它们。对于传出函数参数,您可以使用可能产生较小代码的push
编译器选项来请求-mpush-args
指令。
至于浪费的内存,你可能没有启用优化编译(这当然会完全消除你的b
和c
,因为它们没有被使用;))
每个进程都有自己的虚拟内存地址空间,因此任何其他人都无法使用从堆栈中分配的内存。