原创作品转载请注明出处
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
寻址方式:
(AT&T)
movl %eax,%edx 寄存器寻址
movl $0x12345678,%edx 立即数寻址
movl 0x12345678,%edx 直接寻址
movl (%ebx),%edx 间接寻址
movl 4(%ebx),%edx 变址寻址
程序分析:
C语言程序清单:
int foo(int x)
{
return x + 100;
}
int bar(int x)
{
return foo(x);
}
int main(void)
{
return bar(10) + 1;
}
gcc -S -o main.c 若是64位系统加上 -m32以便按照x86 32位程序编译
生成的汇编代码:
foo:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
addl $100, %eax
popl %ebp
ret
bar:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl 8(%ebp), %eax
movl %eax, (%esp)
call foo
leave
ret
main:
pushl %ebp
movl %esp, %ebp
subl $4, %esp
movl $10, (%esp)
call bar
addl $1, %eax
leave
从main处开始执行程序,堆栈状态分析如图所示:
图中地址使用偏移入口点偏移量的表示方式,比较直观。
红色数据:地址数据(入口点偏移量表示)
绿色数据:立即数
紫色数据:执行语句时的寄存器值
运行分析:
小结:
函数调用时的参数与越多则调用者要为被调用函数压入更大的堆栈空间,此时便能很好的解释为何有些死递归函数在运行一段时间后程序终止的原因了,即堆栈上溢。就算是无参数的递归也至少会在一次调用后压入一次ebp来保存堆栈指针esp