简单C程序运行过程分析(反汇编)

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

依照学术诚信条款,我保证此回答为本人原创,所有回答中引用的外部材料已经做了出处标记。原创作品转载请注明出处 。

 

一、编写代码并生成汇编码。

1、代码如下:(来自课程作业)

实际截图:


图1.代码截图

2、编译生成汇编代码

 简化后的汇编代码:

 

 为了真实性,晒一下截图:

1
图2. 反汇编代码截图

二、汇编代码运行过程分析

####################################################

  • 第17行,main函数入口,开始执行main函数。
    3
  • 第18~19行,%ebp寄存器中的值入栈,然后将%esp中的值复制到%ebp中。
    这一操作就是“保存现场”,即保存当前状态下的工作栈的数据,用于未来退出函数时能够退回到之前的操作指令中。
    4
  • 第20行,%esp寄存器的值减去4个字节。表示栈顶减少4个字节,因为栈顶向低地址生长,所以会空出4个字节,用来存放数据“111”。
  • 第21行,将立即数“111”存放至栈顶位置。
  • 第22行,call f,eip入栈,然后跳转至第9行函数f的入口处。

###############################################

  • 第9~10行,同18~19行,“保存现场”的操作而已。
  • 第11行,%esp减去4个字节,空出来的空间用来存放未来的数据。
  • 第12行,将距%ebp偏移值为8的数据保存至%eax寄存器中。数据正好是代码中的“111”。
  • 第13行,将%eax寄存器中的值存放至栈顶位置。
  • 第14行,调用函数g,eip入栈,跳转至第2行函数g的入口处。
    ###############################################
  • 第2~3行,保存现场操作。
  • 第4行,将距%ebp偏移值为8的数据保存至%eax寄存器中,也就是将数值“111”保存至%eax中。
  • 第5行,将立即数333与%eax寄存器中的数值相加,并保存在%eax寄存器中。
  • 第6行,pop操作,将当前栈顶位置的ebp-2恢复至%ebp中,然后%esp的值自动加4。

################################################

  • 第7行,ret,即:popl %eip,退回至函数f。
    13
  • 第15行,leave,即:movl  %ebp, %esp + popl %ebp
        
  • 第16行,ret,同上,将栈顶的eip-0弹出,eip退回到main()中第23行。
  • 第23行,addl    $222, %eax,将立即数222加上%eax,结果保存在%eax中。
  • 第24行,leave,即:movl %ebp, %esp + popl %ebp。
       

 

  • 第25行,ret,退出main(),程序运行结束,中间结果默认保存在了%eax中。

三、作业小结。

(对“计算机是如何工作的”理解)

        从电路角度来说,计算机不过是一堆电子门电路的组合、叠加,因此其运行也就是分别代表0、1两个数值的高低电平所实现的。根据冯·诺依曼提出的“输入-存储-运算-输出”的结构,计算机的功能由运算器、存储器、控制器等核心部分组成。CPU内部有寄存器作为临时存储器,运算器,也有很重要的控制器。因此,计算机运算过程就是不间断地“取数据 - 运算 - 存数据”的循环。

        从语言层面来讲,汇编语言是最接近机器语言的编程语言。实际上,每一条汇编指令都是一长串机器语言的集合。

        每次开始执行一个程序,首先内存中需要一段空间用作程序的运行栈,然后利用栈“后进先出”的特性来记录程序的运行状态以及临时保存一些寄存器的值。CPU内部的运算器在控制器的控制下不断地与存取寄存器中的值,同时也通过总线与内存进行交互。

发表评论

电子邮件地址不会被公开。 必填项已用*标注