lab1:通过汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的

李俊锋 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ”

一.实验内容

 

1.反汇编如下程序

[cpp] view plain copy
 
 print?
  1. int g(int x)  
  2. {  
  3.   return x + 4;  
  4. }  
  5.    
  6. int f(int x)  
  7. {  
  8.   return g(x);  
  9. }  
  10.    
  11. int main(void)  
  12. {  
  13.   return f(7) + 3;  
  14. }  


2.分析分析汇编代码的工作过程中堆栈的变化


二.实验原理


需要用到的知识:





三.实验过程


3.1使用如下命令,将c代码编译成汇编语言

[plain] view plain copy
 
 print?
  1. <span style="font-size:14px;">gcc –S –o main.s main.c -m32</span>  


3.2 得到的汇编代码如下图所示:

[html] view plain copy
 
 print?
  1. g:  
  2.     pushl   %ebp  
  3.     movl    %esp, %ebp  
  4.     movl    8(%ebp), %eax  
  5.     addl    $4, %eax  
  6.     popl    %ebp  
  7.     ret  
  8.       
  9. f:  
  10.     pushl   %ebp      
  11.     movl    %esp, %ebp  
  12.     subl    $4, %esp  
  13.     movl    8(%ebp), %eax  
  14.     movl    %eax, (%esp)  
  15.     call    g  
  16.     leave  
  17.     ret  
  18.       
  19. main:  
  20.     pushl   %ebp  
  21.     movl    %esp, %ebp  
  22.     subl    $4, %esp  
  23.     movl    $7, (%esp)  
  24.     call    f  
  25.     addl    $3, %eax  
  26.     leave  
  27.     ret  
  28.       


3.3 分析每一条汇编代码以及函数栈的变化:

(1)pushl %ebp

本条指令的意思是将ebp寄存器指向的压栈,同时esp的值减4,栈如下图所示:(假设ebp和esp的值都是100)


(2)movl %esp, %ebp

将esp的值赋值给ebp,栈如下图所示:


(3)subl $4, %esp

本指令将esp的值减4,栈如下图所示:


(4)movl $7, (%esp)

本指令将数值7存到esp所指向的内存单元中,栈如下图所示:


(5)call f

本指令调用f函数,同时将返回地址压栈,返回地址就是main函数中下一条指令addl $3, %eax的地址,栈如下图所示:


(6)pushl %ebp

本指令再次将ebp压栈,栈如下所示:


(7)movl %esp, %ebp

本指令将esp的值赋值给ebp寄存器,栈如下图所示:


(8)subl $4, %esp

本指令是将esp的值减4,将esp向下移一位,栈如下图所示:


(9)movl 8(%ebp), %eax

将ebp+8单元中的值,也就是7赋值给eax寄存器,栈不变

(10)movl %eax, (%esp)

将eax中的值赋值给esp指向的单元中,栈如下图所示:


(11)call g

调用g函数,并将下一条指令leave的地址,也就是返回地址压栈,栈如下图所示:


(12)pushl %ebp

将ebp的值压栈,栈如下图所示:


(13)movl %esp, %ebp

将esp中的值赋值给ebp,栈如下图所示:


(14)movl 8(%ebp), %eax

将ebp+8单元中的值赋值7给eax寄存器,栈无变化

(15)addl $4, %eax

将eax中的值加4,结果存到eax中,也就是eax=7+4=11,程序中通常使用eax保存函数的返回值。

(16)popl %ebp

出栈,将值保存到ebp中,栈如下图所示:


(17)ret

函数返回,同时出栈,将下一条指令的值保存到eip中,栈如下图所示:


(18)leave

首先清空栈,将ebp中的值复制给esp,之后出栈,将值复制给ebp,栈如下图所示:


(19)ret

出栈,将值赋值给eip,栈如下图所示:


(20)addl $3, %eax

将eax中的值加3,结果保存在eax中,即:eax=11+3=14,栈不变

(21)leave

清空栈,将ebp中的值赋值给esp,同时出栈,将值保存到ebp中,栈如下图所示:


(22)ret

主函数返回,程序结束。


四.实验总结


计算机是如何工作的?

根据冯诺依曼结构,计算机可以分为控制器,存储器,运算器,输入设备,和输出设备。程序在运行是需要通过输入设备将程序的二进制机器码读入到内存之中,

内存中又分为代码段和数据段,代码段中的每一条指令指明了cpu下一步需要做的操作。计算机在运行时,先从内存中取出第一条指令,通过控制器的译码,

按指令的要求,从存储器中取出数据进行指定的运算和逻辑操作等加工,然后再按地址把结果送到内存中去。接下来,再取出第二条指令,

在控制器的指挥下完成规定操作。依此进行下去。直至遇到停止指令。最后将处理结果通过输出设备输出到显示器等设备上。


本次实验主要是让我们通过对at&t汇编的学习了解在程序运行时栈的变化。虽然内容并不是很多,但是受益匪浅,因为这门实验让我在信息安全课程之后,能更加深入的

了解at&t汇编的变成方法,对我学习linux系统大有裨益。

原文地址:https://www.cnblogs.com/crowpurple/p/5248353.html