我在C中编写了简单的函数,
void GetInput()
{
char buffer[8];
gets(buffer);
puts(buffer);
}
当我在gdb的反汇编程序中对它进行反汇编时,它会进行以下反汇编。
0x08048464 <+0>: push %ebp
0x08048465 <+1>: mov %esp,%ebp
0x08048467 <+3>: sub $0x10,%esp
0x0804846a <+6>: mov %gs:0x14,%eax
0x08048470 <+12>: mov %eax,-0x4(%ebp)
0x08048473 <+15>: xor %eax,%eax
=> 0x08048475 <+17>: lea -0xc(%ebp),%eax
0x08048478 <+20>: mov %eax,(%esp)
0x0804847b <+23>: call 0x8048360 <gets@plt>
0x08048480 <+28>: lea -0xc(%ebp),%eax
0x08048483 <+31>: mov %eax,(%esp)
0x08048486 <+34>: call 0x8048380 <puts@plt>
0x0804848b <+39>: mov -0x4(%ebp),%eax
0x0804848e <+42>: xor %gs:0x14,%eax
0x08048495 <+49>: je 0x804849c <GetInput+56>
0x08048497 <+51>: call 0x8048370 <__stack_chk_fail@plt>
0x0804849c <+56>: leave
0x0804849d <+57>: ret
现在请看第3行,0x08048467 <+3>: sub $0x10,%esp
,我只有8个字节被分配为本地变量,那么为什么编译器分配16个字节(0x10)。
其次,xor %gs:0x14,%eax
的含义是什么。
@Edit:如果是优化,有没有办法阻止它。
感谢。
答案 0 :(得分:12)
两件事:
关于您应该单独询问的其他问题,xor %gs:0x14,%eax
显然是stack protection mechanism的一部分,默认情况下已启用。如果您使用的是GCC,请使用-fno-stack-protector
将其关闭。
答案 1 :(得分:5)
除了已经给出的其他答案之外,gcc更倾向于保持堆栈16字节对齐以便在堆栈上存储SSE值,因为一些(全部?)SSE指令要求它们的内存参数是16字节对齐的。 / p>
答案 2 :(得分:4)
这更多地基于Pascal的答案,但在这种情况下,可能是因为堆栈保护机制。
你分配8个字节,这是公平的,并与堆栈指针一起考虑。此外,当前堆栈保护地址保存到%ebp
,它指向以下行中当前堆栈帧的 top
0x0804846a <+6>: mov %gs:0x14,%eax
0x08048470 <+12>: mov %eax,-0x4(%ebp)
这似乎需要四个字节。鉴于此,其他四个字节可能用于某种形式的对齐,或者在以下行中与其他一些堆栈信息一起使用:
=> 0x08048475 <+17>: lea -0xc(%ebp),%eax
0x08048478 <+20>: mov %eax,(%esp)