反汇编一个简单的C程序

1、实验要求

使用:

gcc –S –o test.s test.c -m32

命令编译成汇编代码,对汇编代码进行分析总结。其中test.c的具体内容如下:

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

2、实验过程

  • 使用vim对test.c进行编辑,将上述代码键入
  • 使用gcc对test.c编译,产生test.s文件
gcc -S -o test.s test.c -m32

如下图所示:

  • 使用vim查看test.s文件

    查看test.s文件,如下图所示:



    “.”开通的所有代码为链接时候的辅助信息,不会被实际执行,我们可以把这些代码删除,删除后的代码即为纯净的汇编代码,如下图所示:

3、实验分析

  • 寄存器&寻址方式

    • 通用寄存器:

      • AX:累加器
      • BX:基地址寄存器
      • CX:计数寄存器
      • DX:数据寄存器
      • BP:堆栈基址针
      • SI、DI:变址寄存器
      • SP:堆栈顶指针
    • 段寄存器
      • CS:代码段寄存器,指向包含程序指令的段。
      • SS:栈段寄存器,指向包含当前程序栈的段。
      • DS:数据段寄存器,指向包含静态数据或者全局数据段。
      • ES:附加寄存器,指向附加数据段。
    • 寻址方式
      • movl %eax,%edx <-> edx=eax 寄存器寻址
      • movl $0x123,%edx <-> edx=0x123 立即寻址
      • movl 0x123,%edx <-> edx=*(int32_t*)0x123 直接寻址
      • movl (%ebx),%edx <-> edx=*(int32_t*)ebx 间接寻址
      • movl 4(%ebx),%edx <-> edx=*(int32_t*)(ebx+4) 变址寻址
  • 汇编代码流程分析

    • 汇编代码依然从main函数读起

      • eip寄存器从main函数起自+1,指向当前执行的指令语句(未遇到特殊指令时)
      • ebp寄存器始终指向栈底,esp寄存器始终指向栈顶,eax寄存器用来暂存一些数值(如函数的返回值)
      • ebp入栈
      • 把ebp值赋予给esp
      • 将esp值减4,指向下一栈存储空间
      • 将数值2018存在esp所指的存储空间中
    • 调用f函数

      • ebp入栈
      • 把ebp值赋予给esp
      • 将esp减4,指向下一栈地址空间
      • 将ebp变址寻址8,即向上退两个栈空间,并将此空间值赋给eax
      • 将eax的内容赋予给esp
    • 调用g函数

      • 对ebp进行压栈
      • 把ebp值赋予给esp
      • 将ebp变址寻址8,即向上退两个栈空间,并将此空间值赋给eax
      • 将eax储存的数值加9228
      • 出栈
      • 返回f函数call语句的下一句(leave)
    • 返回main函数

      • 返回main的call指令下一句(addl)
      • 将eax储存的数加9228
      • esp指向ebp位置,ebp指向栈中指向的位置(leave作用)
      • 返回
  • 堆栈变化分析

    初始化状态esp和ebp都在栈底:



    后指令代码从main函数顺序执行:







    执行到call f指令,eip记录call指令的下一条语句位置,此时代码跳转至f函数执行:













    执行到call g指令,eip记录call指令下一条语句位置,此时代码跳转至g函数执行:









    此时,g函数执行到ret,返回f函数call的下一条语句leave:











    至此,整个指令运行完成,堆栈为空。

4、实验总结

汇编语言是计算机的低级语言,真正的深入了解汇编语言对于我们深入理解计算机系统有着极大的帮助,更是为我们未来linux内核分析的深入学习打下坚实基础。本次使用C语言反编译成汇编语言,利用我们熟悉的C语言代码来对照理解汇编指令代码、分析堆栈的变化让我们更好的理解计算机在执行程序的时候是如何工作的。具体来说:

  • 加深了esp、ebp、eip以及eax各自作用的印象
  • 更好的理解了变址寻址的具体过程
  • 更加熟悉了常用的汇编指令
  • 了解了计算机在执行程序时是如何工作的

其他问题

在进行makefile的测试时,在vim中写好了Makefile,在进行make时,shell提示没有找到make指令,我意识到应该是没有内置此指令,便使用sudo apt-get install make获取make指令,但shell提示:

sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set

应该是账户的权限不够,但我想要切换到系统内置的root账户,要求我输入密码,但我好像并不知道root的密码……

经过一系列的资料查询,参考了此篇博文的方法,进入recovery模式更改root账户密码。重启后,使用root账户,sudo apt-get install make执行成功,make命令成功安装。

出现这样的小插曲,也算是在本次作业之外的一个小收获。

《Linux内核原理与分析》第二周作业的更多相关文章

  1. 2019-2020-1 20199303<Linux内核原理与分析>第二周作业

    2019-2020-1 20199303第二周作业 1.汇编与寄存器的学习 寄存器是中央处理器内的组成部份.寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令.数据和位址.在中央处理器的控制部件中 ...

  2. 20169219 linux内核原理与分析第二周作业

    "linux内核分析"的第一讲主要讲了计算机的体系结构,和各寄存器之间对数据的处理过程. 通用寄存器 AX:累加器 BX:基地址寄存器 CX:计数寄存器 DX:数据寄存器 BP:堆 ...

  3. 2019-2020-1 20199314 <Linux内核原理与分析>第二周作业

    1.基础学习内容 1.1 冯诺依曼体系结构 计算机由控制器.运算器.存储器.输入设备.输出设备五部分组成. 1.1.1 冯诺依曼计算机特点 (1)采用存储程序方式,指令和数据不加区别混合存储在同一个存 ...

  4. Linux内核原理与分析-第二周作业

    写之前回看了一遍秒速五厘米:如果

  5. Linux内核原理与分析-第一周作业

    本科期间,学校开设过linux相关的课程,当时的学习方式主要以课堂听授为主.虽然老师也提供了相关的学习教材跟参考材料,但是整体学下来感觉收获并不是太大,现在回想起来,主要还是由于自己课下没有及时动手实 ...

  6. 2019-2020-1 20199314 <Linux内核原理与分析>第一周作业

    前言 本周对实验楼的Linux基础入门进行了学习,目前学习到实验九完成到挑战二. 学习和实验内容 快速学习了Linux系统的发展历程及其简介,学习了下的变量.用户权限管理.文件打包及压缩.常用命令的和 ...

  7. 2018-2019-1 20189221《Linux内核原理与分析》第一周作业

    Linux内核原理与分析 - 第一周作业 实验1 Linux系统简介 Linux历史 1991 年 10 月,Linus Torvalds想在自己的电脑上运行UNIX,可是 UNIX 的商业版本非常昂 ...

  8. 2020-2021-1 20209307 《Linux内核原理与分析》第九周作业

    这个作业属于哪个课程 <2020-2021-1Linux内核原理与分析)> 这个作业要求在哪里 <2020-2021-1Linux内核原理与分析第九周作业> 这个作业的目标 & ...

  9. 20169212《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 这一周学习了MOOCLinux内核分析的第一讲,计算机是如何工作的?由于本科对相关知识的不熟悉,所以感觉有的知识理解起来了有一定的难度,不过多查查资 ...

  10. 20169210《Linux内核原理与分析》第二周作业

    <Linux内核原理与分析>第二周作业 本周作业分为两部分:第一部分为观看学习视频并完成实验楼实验一:第二部分为看<Linux内核设计与实现>1.2.18章并安装配置内核. 第 ...

随机推荐

  1. struts2注释返回json数据

  2. zookeeper及kafka集群搭建

    zookeeper及kafka集群搭建 1.有关zookeeper的介绍可参考:http://www.cnblogs.com/wuxl360/p/5817471.html 2.zookeeper安装 ...

  3. js的柯里化currying

    转载:http://www.zhangxinxu.com/wordpress/2013/02/js-currying/ 我自己的理解柯里化就是这样的,(1)必须返回匿名函数,(2)参数复用. 1. 参 ...

  4. Caffarelli 关于自由边界正则性的论文C1

    Caffarelli 关于自由边界正则性的论文 接下来主要想叙述一下Caffarelli的C1文章中的一些想法,这是最近这几天看的文献. 对于从自由边界的Lipschitz正则性到$C^{1,\alp ...

  5. 浅谈awk命令

    简介 awk是一个强大的文本分析工具,相对于grep.sed命令,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,然后将每行切片,再对切开的部分进行处理. awk有 ...

  6. [spring源码] 小白级别的源码解析IOC容器的依赖注入(三)

    上一篇介绍了ioc容器的初始化过程,主要完成了ioc容器建立beanDefinition数据映射.并没有看到ioc容器对bean依赖关系进行注入. 接口getbean就是出发依赖注入发生的地方.下面从 ...

  7. 使用cookie记录页面跳转次数,然后从最后一级页面跳转回首页面

    1.首先,给出cookie设置,获取,删除的操作函数. function setCookie(name,value) {          var Days = 30;          var ex ...

  8. MYSQL Statement violates GTID consistency: CREATE TABLE ... SELECT. 错误代码: 1786 问题

    1.在MYSQL中,执行建表语句时CREATE TABLE  aaaa  AS SELECT * FROM menu;  报: 错误代码: 1786Statement violates GTID co ...

  9. java截取字符串,第4位以后的字符串用*代替

    public class F { public static void main(String[] args) { /**截取字符串,第4位以后的字符串用*代替*/ String s = " ...

  10. SVN客户端使用

    1.在SVN服务器添加新的用户,复制SVN URL(路径/目录). 2.在客户端电脑上下载安装SVN客户端,配置hosts文件中的内容和SVN服务器的hosts文件内容一致. hosts路径:C:\W ...