标签:
本节通过反汇编可执行文件得到的文件,研究函数栈帧的相关内容;
#include <stdio.h> #include <iostream> using namespace std; int z = 10; int add(int x, int y) { return x+y+z; } int inc20(int x) { int y = 10; return add(x, y); } int main(void) { int a = 30; a = inc20(a); cout << a << endl; return 0; }说明几点
(1)本节只研究main和inc20、add之间的函数栈帧,对于cout,以及main函数之前和之后的启动和结束代码不作研究;
080486ac <_Z3addii>: 80486ac: 55 push %ebp 80486ad: 89 e5 mov %esp,%ebp 80486af: 8b 55 08 mov 0x8(%ebp),%edx 80486b2: 8b 45 0c mov 0xc(%ebp),%eax 80486b5: 01 c2 add %eax,%edx 80486b7: a1 84 9a 04 08 mov 0x8049a84,%eax 80486bc: 01 d0 add %edx,%eax 80486be: 5d pop %ebp 80486bf: c3 ret 080486c0 <_Z5inc20i>: 80486c0: 55 push %ebp 80486c1: 89 e5 mov %esp,%ebp 80486c3: 83 ec 10 sub $0x10,%esp 80486c6: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%ebp) 80486cd: ff 75 fc pushl -0x4(%ebp) 80486d0: ff 75 08 pushl 0x8(%ebp) 80486d3: e8 d4 ff ff ff call 80486ac <_Z3addii> 80486d8: 83 c4 08 add $0x8,%esp 80486db: c9 leave 80486dc: c3 ret 080486dd <main>: 80486dd: 8d 4c 24 04 lea 0x4(%esp),%ecx 80486e1: 83 e4 f0 and $0xfffffff0,%esp 80486e4: ff 71 fc pushl -0x4(%ecx) 80486e7: 55 push %ebp 80486e8: 89 e5 mov %esp,%ebp 80486ea: 51 push %ecx 80486eb: 83 ec 14 sub $0x14,%esp 80486ee: c7 45 f4 1e 00 00 00 movl $0x1e,-0xc(%ebp) 80486f5: ff 75 f4 pushl -0xc(%ebp) 80486f8: e8 c3 ff ff ff call 80486c0 <_Z5inc20i> 80486fd: 83 c4 04 add $0x4,%esp 8048700: 89 45 f4 mov %eax,-0xc(%ebp) 8048703: 83 ec 08 sub $0x8,%esp 8048706: ff 75 f4 pushl -0xc(%ebp) 8048709: 68 c0 9a 04 08 push $0x8049ac0 804870e: e8 e9 fd ff ff call 80484fc <_ZNSolsEi@plt> 8048713: 83 c4 10 add $0x10,%esp 8048716: 83 ec 08 sub $0x8,%esp 8048719: 68 6c 85 04 08 push $0x804856c 804871e: 50 push %eax 804871f: e8 38 fe ff ff call 804855c <_ZNSolsEPFRSoS_E@plt> 8048724: 83 c4 10 add $0x10,%esp 8048727: b8 00 00 00 00 mov $0x0,%eax 804872c: 8b 4d fc mov -0x4(%ebp),%ecx 804872f: c9 leave 8048730: 8d 61 fc lea -0x4(%ecx),%esp 8048733: c3 ret说明几点
(1)首先在_Z3addii找出z变量的地址和相关信息;
sykpour@sykpour:~/Desktop$ readelf -s test | grep 8049a84 75: 08049a84 4 OBJECT GLOBAL DEFAULT 23 z(2)立即数前面的标识是$,popl为双字(单字为16字节)出栈,对于寄存器而言pop %esp也是栈中双字赋值给esp;如movl $0xa,-0x4(%ebp)表示将立即数0xa存放到ebp+4地址处;而mov 0x8(%ebp),%edx表示将ebp+8地址处的内容存放到edx寄存器中;
080486ac <_Z3addii>: 80486ac: 55 push %ebp 80486ad: 89 e5 mov %esp,%ebp 80486af: 8b 55 08 mov 0x8(%ebp),%edx #取参数x到edx 80486b2: 8b 45 0c mov 0xc(%ebp),%eax #取参数y到eax 80486b5: 01 c2 add %eax,%edx #x=x+y; 80486b7: a1 84 9a 04 08 mov 0x8049a84,%eax #取z的内容到eax 80486bc: 01 d0 add %edx,%eax #z=z+x; 80486be: 5d pop %ebp 80486bf: c3 ret 080486c0 <_Z5inc20i>: 80486c0: 55 push %ebp 80486c1: 89 e5 mov %esp,%ebp 80486c3: 83 ec 10 sub $0x10,%esp 80486c6: c7 45 fc 0a 00 00 00 movl $0xa,-0x4(%ebp) #局部变量y的值 80486cd: ff 75 fc pushl -0x4(%ebp) #add的参数y 80486d0: ff 75 08 pushl 0x8(%ebp) #add的参数x,ebp是在main函数的栈中找的值 80486d3: e8 d4 ff ff ff call 80486ac <_Z3addii> 80486d8: 83 c4 08 add $0x8,%esp #调整栈指针 80486db: c9 leave 80486dc: c3 ret 080486dd <main>: 80486dd: 8d 4c 24 04 lea 0x4(%esp),%ecx 80486e1: 83 e4 f0 and $0xfffffff0,%esp 80486e4: ff 71 fc pushl -0x4(%ecx) 80486e7: 55 push %ebp #保存栈帧寄存器 80486e8: 89 e5 mov %esp,%ebp #栈帧指针指向栈指针 80486ea: 51 push %ecx #保护ecx寄存器的内容 80486eb: 83 ec 14 sub $0x14,%esp #调整栈指针,存放局部变量 80486ee: c7 45 f4 1e 00 00 00 movl $0x1e,-0xc(%ebp) #局部变量a的值 80486f5: ff 75 f4 pushl -0xc(%ebp) #inc20的参数x 80486f8: e8 c3 ff ff ff call 80486c0 <_Z5inc20i> 80486fd: 83 c4 04 add $0x4,%esp #调整栈指针 8048700: 89 45 f4 mov %eax,-0xc(%ebp) #cout打印的参数,直接从add的eax中取回的 8048703: 83 ec 08 sub $0x8,%esp 8048706: ff 75 f4 pushl -0xc(%ebp) 8048709: 68 c0 9a 04 08 push $0x8049ac0 804870e: e8 e9 fd ff ff call 80484fc <_ZNSolsEi@plt>
标签:
原文地址:http://blog.csdn.net/skyuppour/article/details/44892047