- 1、本文档共14页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
-PAGE13-
第PAGE1页共NUMPAGES14页
实验四:使用GDB对C程序进行反汇编
1.实验目的
(1)理解并掌握C程序编译成可执行的目标文件的方法和原理;
(2)掌握GDB的使用并对可执行文件反汇编;
(3)根据得到的汇编指令分析C在函数调用时栈的变化;
2.实验内容
(1)使用GDB对getsum和main函数反汇编
(2)通过反汇编,根据得到的汇编指令分析函数调用时栈的变化;
3.实验方法(实验步骤)
步骤:
第一步:双击打开进入linux的终端,用vi新建一个stack_demo.c的文件
第二步:创建成功之后,输入“a”或“o”或“i”进行插入编辑写入模式
第三步:开始写我们的代码
第四步:代码编辑完成之后,按“Esc”间退出编辑模式
第五步:输入“:wq”对我们刚才编辑的代码进行保存退出
第六步:输入“gcc–gstack_demo.c-ostack_demo”命令运行代码的编译成可执行文件
第七步:然后输入“gdbstack_demo”进行代码的反汇编
第八步:输入“disasgetsum”+回车,得到getsum函数栈
第九步:输入“disasmain”+回车,得到main栈
4.实验过程(源代码、配置清单必须带注释)
注释:esp:栈顶指针sub:减法指令 mov:传送指令
ebp:存取堆栈指针ret:返回(地址出栈)指令 and:逻辑与运算
push:暂存数据(进栈) add:加法指令 call:子程序调用
shl:向左逐位移动*次 shr:向右逐位移动*次 leave:退出栈机制
源码
运行结果:
main栈+注释
getsum函数栈
5.思考题
把下面的C程序编译成可执行的目标文件,使用GDB对可执行文件反汇编,根据得到的汇编指令分析C在函数调用时栈的变化。
分析过程:
main栈
L1执行push%ebp:main函数先保存之前的帧指针%ebp。此时即进入了main函数的栈。描述如下:
L2执行mov%esp,%ebp:L1已经保存了之前函数的%ebp,接下来需要修改函数main的栈帧指针,指示main栈的开始,即修改%ebp,使其内容为寄存器%esp的内容,即:%ebp=%esp,此时栈结构如下:
L3执行sub$0x18,%esp:此处即修改main函数栈的大小。由于在linux里,栈增长的方向是从大到小,所以这里是%esp=%esp-$0x18;关于为什么减去$0x18,即十进制的24,GCC坚持一个x86编程指导方针,也就是一个函数使用的所有栈空间必须是16字节的整数倍。包括保存%ebp值的4个字节和返回值的4个字节,采用这个规则是为了保证访问数据的严格对齐,所以这里main函数栈的大小=24+4+4=32(分配的24,保存%ebp的4,保存返回值的4)。此时栈结构如下:
L11movl$0x3,-0x4(%ebp),L12?movl$0x4,-0x8(%ebp),这两行是定义变量x,y,此时栈的结构如下:
L13mov?-0x8(%ebp),%eax;L14mov?%eax,0x4(%esp)这两行是把变量y的地址赋给%esp+4,栈结构如下:
L14mov?-0x4(%ebp),%eax;L15mov?%eax,(%esp)这两行是把变量y的地址赋给%esp,栈结构如下:
L16call0x804834cgetsum可以看出调用了getsun函数,从上面的第6步知道实参是调用函数传入栈,且逆序传入,这里call指令会把下一行指令的地址压入栈,即地址指令为:0x804847c,此时栈结构如下:
getsum函数栈
L1push%ebp:同main函数第一步一样,先保存之前函数的栈帧,即保存main函数的帧指针%ebp,此时栈情况如下:
L2mov?%esp,%ebp:同上述main描述里面步骤2,修改寄存器%ebp,栈结构如下:
L4?sub?$0x4,%esp:同上述main描述步骤3,修改函数getsum的栈大小,此时栈结构如下:
L5mov?$0x0,-0x4(%ebp);?L6mov?0xc(%ebp),%eax;L7?mov0x8(%ebp),%eax?;L8?mov%eax,-0x4(%ebp):这些功能分别是定义变量,获取得地址,其中L8会修改栈内容,此时栈结构情况如下:
到这里getsum函数即执行完,然后又跳转到main函数开始执行后续指令。后续L16行用到的%eax即之前fun函数的返回值,此时%ebp已经指向了main函数的帧指针,后面已经没有什么可以描述的了,最后还会修
文档评论(0)