Linux用GCC和GDB对C语言进行汇编语言分析

来源:互联网 发布:万网域名自助解析平台 编辑:程序博客网 时间:2024/07/17 20:18
前言
为能深入学习Linux,提高编程能力,探寻奇妙的编程之旅,参加了网易的《Linux内核分析》公开课。
卢晅 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
第一章 原文件处理

C语言源代码:
int a(int x){  return x + 5;} int b(int x){  return a(x);} int main(void){  return  b(7) + 6;}


得出的汇编代码:
a:pushl%ebpmovl%esp, %ebpmovl8(%ebp), %eaxaddl$5, %eaxpopl%ebpretb:pushl%ebpmovl%esp, %ebppushl8(%ebp)callaaddl$4, %espleaveretmain:pushl%ebpmovl%esp, %ebppushl$7callbaddl$4, %espaddl$6, %eaxleave


第二章 调试
实验环境为:Ubuntu 14.10
在终端中输入了:gcc -S -o main.s main.c -m32
接着打开main.s并通过gdb命令进行分析:
gdb ./maingdb layout asmgdb layout regs

然后得到如下结果:


所需要注意的是,如果gdb提示The program is not being run.则输入r。如果要结束调试则输入kill,退出输入q。
设置断点
(gdb)b main(gdb)b a(gdb)b b
接着:输入r运行。
然后输入:
(gdb)si
进行逐句分析。

结果发现一个有趣的现象便是:函数真正开始的地方为:<function name+3>的位置。

输入(gdb)layout regs查看寄存器的结果:
这里我选了几张,因为步骤太多了:
开始:
第一步:
最后:

第三章 分析
a:
pushl %ebp
esp先指向下一位,将esp和ebp指向同一地方。
movl %esp, %ebp
将esp和ebp指向同一地方。
movl 8(%ebp), %eax
将epb的值8赋值给eax。
addl $5, %eax
eax的值加5。
popl %ebp
相当于两步:
movl (%esp),%eax
addl $4,%esp
则:将esp所指向的值赋值给eax,接着esp向上移动一位。
ret
相当于pop eip(*)
则:eip的值赋值给eax,而esp则指向上一位内存空间。
b:
pushl %ebp
esp先指向下一位,将ebp的值赋值给esp所指的地方。
movl %esp, %ebp
将esp和ebp指向同一地方。
pushl 8(%ebp)
将8赋值给ebp所指向的地址空间。
call a
将eip的值记为下一条指令的地址,esp指向下一个地址空间。这时转向a函数。
addl $4, %esp
esp往上移一位4。
leave
esp和指向同一位置ebp。
然后将esp所指向的内存空间的值付给eax。
esp往上移一位。
ret
main:
pushl %ebp
相当于两步:
subl $4 %esp
movl %ebp,(%esp)
esp先指向下一位,将ebp的地址值赋值给esp所指的地方。
movl %esp, %ebp
将esp和ebp指向同一地方。
pushl $7
esp向下移一位,然后将7赋值给esp所指的地方。
call b
分为两步:
pushl %eip(*)
movl b的地址 %eip(*)
将eip的值记为下一条指令的地址,esp指向下一个地址空间。这时转向b函数。
addl $4, %esp(ubuntu多余代码,不予以分析)
addl $6, %eax
eax的值加6。
leave
esp和指向同一位置ebp。
然后将esp所指向的内存空间的值赋值给eax。
esp往上移一位。
第四章 总结
在生成代码的时候,我发现生成了很多多余代码。而现在我才发现,这些代码都是因为自己没有写对函数名造成的。由于我更改了老师的代码,却没有更改相应的函数名导致了错误。也算是给自己的教训。还有,我还发现了一段多余的代码:addl $4,%esp,不知道是什么原因。这个是为了什么设定的呢?希望大家来讨论一下。
0 0
原创粉丝点击