《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

时间:2021-03-14 00:56:06

一个简单c程序

分析一个简单的c程序《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码 main.c 如下图:

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

 

用命令 gcc –S –o main.s main.c -m32编译成汇编文件。在汇编文件中有许多的虚指令并不会形成机器指令,为了使分析简单我们把大部分去掉:

得到如下图所示:

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

 栈的介绍

APUE中指出每一个c程序,都有一个独立的地址空间,在内存中的典型布局如下:

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

 对栈的操作和我们在数据结构中的栈的操作是类似的,ebp,esp(具体名称与cpu体系结构相关) 这两个寄存器直接与栈的操作相关。

 栈地址是从高到低的方向分配的。

  1. 开始一个新的栈时,使ebp,esp指向栈的起始地址的下一位。eg:ebp,esp 指向0x10000
  2. pushl操作,esp-4(32位机器为例),此时esp的值为0xfffc,将操作数放入栈
  3. popl操作,将操作数出栈,esp+4

函数调用

call指令调用一个子程序,cpu会转移到去执行子程序代码,为了当子程序执行完时能够准确返回,需要把call指令的下一条指令的地址压入栈。然后为子程序建立一个新的栈,汇编指令如下:

  1. pushl %ebp
  2. movl %esp, %ebp

pushl %ebp 指令将主调程序的栈的基址压入栈,执行movl %esp,%ebp指令后 esp,ebp 都指向新的栈的起始地址的下一位。当要恢复主调函数的栈时,只要执行如下指令,就会恢复主调函数的栈:

  1. movl %ebp,%esp
  2. popl %ebp

这两句汇编可以用leave指令代替,当然也有可能直接执行 popl %ebp 就可以。

 当恢复主调函数的栈时,在栈的栈顶就是即将要执行的指令的地址,通过ret指令,将指令的地址返回给指令计数器,cpu就会从call的下一条指令继续跑下去了。

 

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码

《Linux内核分析》MOOC课程 反汇编一个简单的C程序,分析汇编代码