【发布时间】:2015-10-01 20:28:18
【问题描述】:
当我编译时
#include <stdio.h>
int
main () {
return 0;
}
到 x86 程序集的结果是简单的和预期的:
$> cc -m32 -S main.c -o -|sed -r "/\s*\./d"
main:
pushl %ebp
movl %esp, %ebp
movl $0, %eax
popl %ebp
ret
但是在研究不同的反汇编二进制文件时,函数序言从来没有那么简单。确实,把上面的C源码改成
#include <stdio.h>
int
main () {
printf("Hi");
return 0;
}
结果是
$> cc -m32 -S main.c -o -|sed -r "/\s*\./d"
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $4, %esp
subl $12, %esp
call printf
addl $16, %esp
movl $0, %eax
movl -4(%ebp), %ecx
leave
leal -4(%ecx), %esp
ret
特别是,我不明白为什么这些说明
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
生成了——具体来说,为什么不直接将%esp 存储到%ecx,而不是存储到%esp+4?
【问题讨论】:
-
如果不进行优化,编译器会产生大量垃圾。不仅仅是你的例子,双
subl是对这种不良行为的一个很好的暗示。 -
这里有一个很好的解释:stackoverflow.com/questions/4228261/…