2020-2021-1 20209314《Linux内核原理与分析》第二周作业

实验内容:
反汇编一个简单的C程序

实验过程:

1.创建main.c文件

2.编译并执行main.c文件

3.编译成汇编代码main.s





汇编指令中频繁使用了三个寄存器ebp, esp和eax。
其中ebp是基址指针寄存器;
esp是栈指针寄存器,通常指向栈顶;
eax可以暂存数据,同时也作为函数返回值的默认存储位置。
从main.s文件中可以清楚的看到三个函数的汇编代码
实验分析:

g:
      pushl %ebp //保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
      movl  %esp, %ebp    //将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
      movl  8(%ebp), %eax   //将ebp上移2个地址空间的内容放到eax中,就是数字5
      addl  $1, %eax    //将1与eax中的数相加,也就是6放到eax中
      popl  %ebp //恢复ebp为调用函数基址
      ret //就是f函数中的leave
f:
      pushl %ebp  //保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
      movl  %esp, %ebp  //将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
      subl  $4, %esp  //esp下移一个地址空间(4个字节),为当前函数分配1个栈空间(4个字节)用于存储局部变量
      movl  8(%ebp), %eax  //ebp中的地址上移2个(8个字节)地址空间的内容放到eax中,也就是将数字5放到eax中
      movl  %eax, (%esp)  //将eax中的内容放到esp当前指向的位置
      call  g   //将此时eip中的值压栈,然后将g函数的地址放到eip中,这样程序转而执行g函数。
      leave  //执行完g函数后返回此处,将ebp中的那内容放到esp,将回复ebp为调用函数基址
      ret   //是main函数中的addl $1, %eax
main:
      pushl %ebp      //保存调用函数的基址(ebp中)到栈中,压栈操作此时esp自动下移一个地址空间(4个字节)
      movl  %esp, %ebp   //将esp的内容放到ebp中,设置ebp为当前被调用函数的基址指针,即当前栈顶
      subl  $4, %esp      //esp下移一个地址空间(4个字节),为当前函数分配1个栈空间(4个字节)用于存储局部变量
      movl  $5, (%esp)      //将5放到esp当前指向的位置
      call  f      //将此时eip中的值压栈,然后将f函数的地址放到eip中,这样程序转而执行f函数。
      addl  $1, %eax      //将1与eax中的内容相加,也就是1+6=7,将7放到eax中
      leave            //将ebp中的那内容放到esp,将回复ebp为调用函数基址
      ret      //返回main函数之前的堆栈

可以观察到频繁出现的代码

pushl	%ebp
movl	%esp, %ebp

作用为保存现场,与恢复现场相对应。

实验中遇到的问题和收获:

主要是对各个寄存器的名字及其作用的掌握程度不够熟练,通过查阅庖丁解牛Linux 分析及网上相关知识,
更加熟练的了解了相关寄存器作用知识,学习了函数调用堆相关知识

原文地址:https://www.cnblogs.com/mazhuhong/p/13828581.html