Linux内核分析——分析C程序的反汇编内容

来源:互联网 发布:金盾网络电视台正规吗 编辑:程序博客网 时间:2024/06/05 16:59

作者:耿介之

原创作品转载请注明出处 :http://blog.csdn.net/jiezhi2013/article/details/44132493

《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


1.C程序代码

首先我们写一段小程序:

main.c

int g(int x){    return x + 5;}int f(int x){    return g(x) + 1;}int main(void){    return f(2) + 3;}


2.反汇编

gcc -S -o main.s main.c -m32

得到如下文件

main.s

.file"main.c".text.globlg.typeg, @functiong:.LFB0:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5movl8(%ebp), %eaxaddl$5, %eaxpopl%ebp.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE0:.sizeg, .-g.globlf.typef, @functionf:.LFB1:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5subl$4, %espmovl8(%ebp), %eaxmovl%eax, (%esp)callgaddl$1, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE1:.sizef, .-f.globlmain.typemain, @functionmain:.LFB2:.cfi_startprocpushl%ebp.cfi_def_cfa_offset 8.cfi_offset 5, -8movl%esp, %ebp.cfi_def_cfa_register 5subl$4, %espmovl$2, (%esp)callfaddl$3, %eaxleave.cfi_restore 5.cfi_def_cfa 4, 4ret.cfi_endproc.LFE2:.sizemain, .-main.ident"GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2".section.note.GNU-stack,"",@progbits


其中以.开头的为注释,精简后如下:
g:pushl%ebpmovl%esp, %ebpmovl8(%ebp), %eaxaddl$5, %eaxpopl%ebpretf:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl8(%ebp), %eaxmovl%eax, (%esp)callgaddl$1, %eaxleaveretmain:pushl%ebpmovl%esp, %ebpsubl$4, %espmovl$2, (%esp)callfaddl$3, %eaxleaveret


3.汇编分析

分析当然从main函数开始:

0

  1. pushl %ebp:将当前ebp(堆栈基指针)压栈,同时esp(堆栈顶指针)向下移动1个单位(32位下即4个字节);
  2. movl %esp, %ebp:将esp的值赋给ebp;
  3. subl $4, %esp:将esp下移1个单位(堆栈是从上而下的,所以减去4实则为栈顶加1个单位);
  4. movl $2, (%esp):将值2压栈;
  5. call f:call可以分解为两个动作,pushl %eip(*)和movl $24, %eip(*),这里的$24其实就是把下一行的地址复制给eip(指令寄存器,存放当前指令的下一条指令的地址),ebp下移一个单位,下面从f函数执行:1
  6. 其中 pushl %ebp,movl%esp, %ebp,subl$4, %esp三条指令和前面的1,2,3是一样的,略过;
  7. movl 8(%ebp), %eax:ebp+8即为ebp往上两个单位的位置,我们知道其实指向第4步压入的值2并将其复制为eax(累加器);
  8. movl %eax, (%esp):将eax赋值给esp;
  9. call g:同5;2
  10. g函数中的pushl %ebp,movl%esp, %ebp,movl8(%ebp), %eax同上;
  11. addl $5, %eax:把5加给eax,通过上面我们知道eax现在的值是2,所以现在eax值为2+5 = 7;
  12. popl %ebp:上一个压入ebp是在g函数的开始,所以这里相当于把ebp指向进入g函数之前的位置了,esp也相应的移到上个单位;
  13. ret:即return,相当于popl %eip,而上一个eip是在进入g函数的时候压入的(即call g),至此g函数执行完,继续回到f函数执行,(所计算的值7还保存在eax里)。
  14. addl $1, %eax:再把eax加1,此时eax的值为8;
  15. leave:相当于movl $esp, %eip和popl %ebp两条指令。此时esp指向main函数的call f的下一条指令,ebp指向main函数的ebp了。
  16. ret:同上
  17. addl $3, %eax:eap的值为11了。
  18. leave:同上;
  19. ret:同上。
至此,我们把这一小段反汇编代码看完了。


4.总结

其实我们可以看到,这段C程序在计算机内的执行,其实都是建立在对堆栈操作的基础上的。而堆栈的操作基本也是对栈底、栈顶的操作,所以理解了上面诸如,push、pop、move等操作后,我们就可以对一些简单的程序进行汇编分析了。



0 0
原创粉丝点击