分享
 
 
 

函数调用分析

王朝other·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

测试环境:Red Hat Linux 7.2

注解 :

eip 寄存器内容式当前执行指令的下一条指令的地址;

mov eax, ebx 将寄存器eax内容移到ebx; 机器指令2字节。

leave 指令所做的操作相当于mov ebp, esp 然后 pop ebp; 机器指令1字节。

ret 指令所做的操作相当于pop eip; 机器指令1字节。

call addr 指令所做的操作相当于push eip 然后 jmp addr; 机器指令4字节。

jmp addr 执行所做的操作相当于 mov addr, eip; 机器指令2字节。

注意:我们所说的”相当于”是在功能上的等价,并不是实际机器指令的等价。

1. 编写测试程序,如下:

//file name : cc.c

#include

int foo(int fi,int fj)

{

int fk;

fk=3;

return(0);

}

int main()

{

int mi;

int mj;

mi=1;

mj=2;

foo(mi,mj);

return(0);

}

2. 对代码进行编译:

gcc –g –o cc cc.c

3. 用gdb进行debug:gdb cc

(1) 查看源程序:

(gdb) list

4 {

5 int fk;

6 fk=3;

7 return(0);

8 }

9 int main()

10 {

11 int mi;

12 int mj;

13 mi=1;

(gdb)

14 mj=2;

15 foo(mi,mj);

16

17 return(0);

18 }

(2)查看汇编代码:

(gdb) disass main

Dump of assembler code for function main:

0x8048444 : push %ebp

0x8048445 : mov %esp,%ebp

0x8048447 : sub $0x8,%esp

0x804844a : movl $0x1,0xfffffffc(%ebp)

0x8048451 : movl $0x2,0xfffffff8(%ebp)

0x8048458 : sub $0x8,%esp

0x804845b : pushl 0xfffffff8(%ebp)

0x804845e : pushl 0xfffffffc(%ebp)

0x8048461 : call 0x8048430

0x8048466 : add $0x10,%esp

0x8048469 : mov $0x0,%eax

0x804846e : leave

0x804846f : ret

End of assembler dump.

(gdb) disass foo

Dump of assembler code for function foo:

0x8048430 : push %ebp

0x8048431 : mov %esp,%ebp

0x8048433 : sub $0x4,%esp

0x8048436 : movl $0x3,0xfffffffc(%ebp)

0x804843d : mov $0x0,%eax

0x8048442 : leave

0x8048443 : ret

End of assembler dump.

(3)在主函数设置断点,并执行程序,让程序在main函数刚开始时暂停:

(gdb) break 9

Breakpoint 1 at 0x8048444: file c1.c, line 9.

(gdb) run

Starting program: /home/syf/p/cc

Breakpoint 1, main () at c1.c:10

10 {

(4)查看关键寄存器内容:

(gdb) i reg esp

esp 0xbffffaec 0xbffffaec

(gdb) i reg ebp

ebp 0xbffffb28 0xbffffb28

(gdb) i reg eip

eip 0x8048444 0x8048444

(5)查看栈空间内容:

(gdb) x/32xw 0xbffffae0

0xbffffae0: 0x080494e8 0x080495e4 0xbffffaf8 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

0xbffffb00: 0x080484b0 0x00000000 0xbffffb28 0x400464f1

0xbffffb10: 0x00000000 0xbffffb5c 0x4015ec3c 0x40016300

0xbffffb20: 0x00000001 0x08048330 0x00000000 0x08048351

0xbffffb30: 0x08048444 0x00000001 0xbffffb54 0x080482bc

0xbffffb40: 0x080484b0 0x4000dc14 0xbffffb4c 0x40016944

0xbffffb50: 0x00000001 0xbffffc53 0x00000000 0xbffffc62

注意:ebp内容是:0xbffffb28,这个地址对应的内容是0x00000000;

(6)执行一条机器指令(0x8048444 : push %ebp),即将ebp压栈:

(gdb) si

0x08048445 10 {

(gdb) i reg esp

esp 0xbffffae8 0xbffffae8

(gdb) i reg ebp

ebp 0xbffffb28 0xbffffb28

(gdb) i reg eip

eip 0x8048445 0x8048445

(gdb) x/12xw 0xbffffae0

0xbffffae0: 0x080494e8 0x080495e4 0xbffffb28 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

0xbffffb00: 0x080484b0 0x00000000 0xbffffb28 0x400464f1

可以看到,ebp(内容是0xbffffb28)被压到0xbffffae8处。

(7)执行一条机器指令(0x8048445 : mov %esp,%ebp),即将esp->ebp,查看寄存器内容和堆内容:

(gdb) si

0x08048447 in main () at c1.c:10

10 {

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg esp

esp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048447 0x8048447

(gdb) x/12xw 0xbffffae0

0xbffffae0: 0x080494e8 0x080495e4 0xbffffb28 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

0xbffffb00: 0x080484b0 0x00000000 0xbffffb28 0x400464f1

可以看到,栈空间内容没变,只是寄存器ebp变成了esp的值。

(8) 执行三条机器指令,为mi,mj赋值。

三条指令是:

0x8048447 : sub $0x8,%esp

0x804844a : movl $0x1,0xfffffffc(%ebp)

0x8048451 : movl $0x2,0xfffffff8(%ebp)

这三条指令的作用是为mi,mi赋值。

(gdb) si

13 mi=1;

(gdb) si

14 mj=2;

(gdb) si

15 foo(mi,mj);

(gdb) i reg esp

esp 0xbffffae0 0xbffffae0

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048458 0x8048458

(gdb) x/12xw 0xbffffae0

0xbffffae0: 0x00000002 0x00000001 0xbffffb28 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

0xbffffb00: 0x080484b0 0x00000000 0xbffffb28 0x400464f1

可以看到,系统为mi,mj在栈内分配了空间(对应的地址分别是:0xbffffae4,0xbffffae0),并进行了赋值(分别是:0x00000001,0x00000002)。

(9)执行下一条指令(0x8048458 : sub $0x8,%esp),将堆栈栈空间加8个字节的空间,没有意义,可以略去,在优化代码时,将被略去。

注:优化代码的方法是:gcc –O –o cc cc.c

(gdb) si

0x0804845b 15 foo(mi,mj);

(10)执行下两条指令,堆将要调用的函数foo(int, int)的参数压栈。两条指令是:

0x804845b : pushl 0xfffffff8(%ebp)

0x804845e : pushl 0xfffffffc(%ebp)

这两条指令的作用是对调用的函数foo(int fi, int fj)的参数压栈。

(gdb) si

0x0804845e 15 foo(mi,mj);

(gdb) si

0x08048461 15 foo(mi,mj);

(gdb) i reg esp

esp 0xbffffad0 0xbffffad0

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048461 0x8048461

(gdb) x/12xw 0xbffffad0

0xbffffad0: 0x00000001 0x00000002 0xbffffaf8 0x08048411

0xbffffae0: 0x00000002 0x00000001 0xbffffb28 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

(11)执行下一条指令:0x8048461 : call 0x8048430 。

这条call指令可以分解成两条指令:push eip;jmp 0x8048430。

其作用是保存main函数的foo(int, int)函数调用后的下一条指令的地址(0x8048466),以便foo(int ,int)函数调用返回后在main()函数继续指令,同时还要跳转到foo(int, int)的地址(0x8048430),以便执行函数foo(int ,int);

注意:此时的eip为0x8048466,对应的指令是:0x8048466 : add $0x10,%esp

(gdb) si

foo (fi=1, fj=-1073743020) at c1.c:4

4 {

(gdb) i reg esp

esp 0xbffffacc 0xbffffacc

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048430 0x8048430

(gdb) x/12xw 0xbffffacc

0xbffffacc: 0x08048466 0x00000001 0x00000002 0xbffffaf8

0xbffffadc: 0x08048411 0x00000002 0x00000001 0xbffffb28

0xbffffaec: 0x40046507 0x00000001 0xbffffb54 0xbffffb5c

(12)执行下两条指令,并查看寄存器和堆内容:

这两条指令是:

0x8048430 : push %ebp

0x8048431 : mov %esp,%ebp

这两条指令的作用是对main函数中的 ebp进行压栈,以便返回时用(和第15步对应),同时将esp赋值为ebp(ebp->esp),一般本函数返回(和第16步对应)。

(gdb) si

0x08048431 4 {

(gdb) si

0x08048433 in foo (fi=1, fj=2) at c1.c:4

4 {

(gdb) i reg esp

esp 0xbffffac8 0xbffffac8

(gdb) i reg ebp

ebp 0xbffffac8 0xbffffac8

(gdb) i reg eip

eip 0x8048433 0x8048433

(gdb) x/12xw 0xbffffac8

0xbffffac8: 0xbffffae8 0x08048466 0x00000001 0x00000002

0xbffffad8: 0xbffffaf8 0x08048411 0x00000002 0x00000001

0xbffffae8: 0xbffffb28 0x40046507 0x00000001 0xbffffb54

可以看到ebp的内容被压栈,压在地址0xbffffac8处。

(13)执行下两条指令,并查看寄存器和堆内容:

这两条指令是:

0x8048433 : sub $0x4,%esp

0x8048436 : movl $0x3,0xfffffffc(%ebp)

其作用是为fk赋值。

(gdb) si

7 return(0);

(gdb) i reg esp

esp 0xbffffac4 0xbffffac4

(gdb) i reg ebp

ebp 0xbffffac8 0xbffffac8

(gdb) i reg eip

eip 0x804843d 0x804843d

(gdb) x/12xw 0xbffffac4

0xbffffac4: 0x00000003 0xbffffae8 0x08048466 0x00000001

0xbffffad4: 0x00000002 0xbffffaf8 0x08048411 0x00000002

0xbffffae4: 0x00000001 0xbffffb28 0x40046507 0x00000001

可以看到系统在堆中为fk分配空间(0xbffffac4),并赋值(0x00000003)。

(14)执行下一条指令(0x8048469 : mov $0x0,%eax),其作用是为eax清空,即使返回值为0。

(gdb) i reg esp

esp 0xbffffac4 0xbffffac4

(gdb) i reg ebp

ebp 0xbffffac8 0xbffffac8

(gdb) i reg eip

eip 0x8048442 0x8048442

(gdb) x/12xw 0xbffffac4

0xbffffac4: 0x00000003 0xbffffae8 0x08048466 0x00000001

0xbffffad4: 0x00000002 0xbffffaf8 0x08048411 0x00000002

0xbffffae4: 0x00000001 0xbffffb28 0x40046507 0x00000001

(15)执行下一条指令(0x8048442 : leave),这条指令可以分解为mov ebp esp和pop ebp,其作用使弹出12步中保存的main函数中的ebp,为返回做准备.

(gdb) si

0x08048443 in foo (fi=1, fj=-1073743020) at c1.c:8

8 }

(gdb) i reg esp

esp 0xbffffacc 0xbffffacc

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048443 0x8048443

(gdb) x/12xw 0xbffffacc

0xbffffacc: 0x08048466 0x00000001 0x00000002 0xbffffaf8

0xbffffadc: 0x08048411 0x00000002 0x00000001 0xbffffb28

0xbffffaec: 0x40046507 0x00000001 0xbffffb54 0xbffffb5c

(16)执行下一条指令(0x8048443 : ret),即pop eip,返回11步中保存的返回地址:0x8048466 : add $0x10,%esp。

(gdb) si

0x08048466 in main () at c1.c:15

15 foo(mi,mj);

(gdb) i reg esp

esp 0xbffffad0 0xbffffad0

(gdb) i reg ebp

ebp 0xbffffae8 0xbffffae8

(gdb) i reg eip

eip 0x8048466 0x8048466

(gdb) x/12xw 0xbffffad0

0xbffffad0: 0x00000001 0x00000002 0xbffffaf8 0x08048411

0xbffffae0: 0x00000002 0x00000001 0xbffffb28 0x40046507

0xbffffaf0: 0x00000001 0xbffffb54 0xbffffb5c 0x080482d2

(17)此时,eip为:0x8048466 : add $0x10,%esp,

其后的指令还有:

0x8048466 : add $0x10,%esp

0x8048469 : mov $0x0,%eax

0x804846e : leave

0x804846f : ret

至此函数调用完成,我们不对下面的内容进行分析。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有