1.最简单的代码:
test1.c
int main(){
return 1;
}
编译、反汇编:
gcc test1.c
gdb ./a.out
(gdb) disassemble main
0x08048344 :lea0x4(%esp),%ecx;取出esp寄存器里的值,加上4,将得到值传递给ecx;
0x08048348 :and$0xfffffff0,%esp;使栈地址16字节对齐
0x0804834b :pushl-0x4(%ecx);取出寄存器ecx的值,减去4,即esp的值,将得到的值作为地址,在内存找到该地址对应的值,将其压入栈中。
0x0804834e :push%ebp
0x0804834f :mov%esp,%ebp ;创建Stack Frame(栈框架)
0x08048351 :push%ecx
0x08048352 :mov$0x1,%eax
0x08048357 :pop%ecx
0x08048358 :pop%ebp
0x08048359 :lea-0x4(%ecx),%esp;取出ecx寄存器里的值,减去4,将得到值传递给esp;还原esp的值
0x0804835c :ret
常用指令解释:
CALL指令:
用来调用一个函数或过程,此时,下一条指令地址会被压入堆栈,以备返回时能恢复执行下条指令。RET指令:
用来从一个函数或过程返回,之前CALL保存的下条指令地址会从栈内弹出到EIP寄存器中,程序转到CALL之前下条指令处执行
ENTER指令:
建立当前函数的栈框架,即相当于以下两条指令:pushl %ebp
movl %esp,%ebp
LEAVE指令:
释放当前函数或者过程的栈框架,即相当于以下两条指令:movl ebp esp
popl ebp
2.函数间的调用代码:
假如函数A调用函数B,函数B调用函数C:
/ test2.c
void c(){}
void b(){c();}
void a(){b();}
int main(){
a