电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 服务器
函数调用分析
作者:未知 点击:0
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 
 
测试环境: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

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


文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·LINUX学习笔记--FTP服务器设置篇
·在内核2.6.0-test中安装最新驱动NVIDIA 1.0-4620(共三种方法)
·无软驱和光驱安装Redhat方法
·如何通过PXE的方式远程安装linux(本地无 光 , 软驱)
·网络安装的一点实践
·VI 快速上手
·Linux下Apache并发连接数和带宽控制
·轻轻松松的安装Slackware Linux -- 5.其他非标准安装程序解析
·在Linux下建立强大的FTP搜索引擎(二
·Iptables来限制上QQ

最新文章
·造成服务器不稳定的因素有以下七点
·机房是海外服务器安全稳定重要因素
·UniCache 行业垂直门户网站加速方案
·VPS服务器是主机业务的革命性技术
·如何选好虚拟主机的五个关键细节
·虚拟化技术会造成服务器市场的低迷吗?
·IP KVM打造“保姆”服务的IDC机房
·服务器能耗吞噬资源 优化数据中心
·ASP.NET2.0服务器控件之捕获回传事件
·服务器虚拟化必须考虑的十大重要因素


 
 


版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号