反汇编一个简单的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. 关于decode("utf-8")出现编码错的提示

    data = data.decode("utf-8") 出现错误时候可以加上第二个参数  如下; data = data.decode("utf-8",&quo ...

  2. react-router 4.0(一)

    import React from 'react'; import ReactDOM from 'react-dom' import {Link,Route,HashRouter} from 'rea ...

  3. 变量和关系符和JAVA基本类型笔记与常考面试题

    变量的类型:数值型:整型(byte,short,int,long).浮点型(float,double)非数值型:布尔类型(boolean),字符型(char),字符串类型(String),其他引用型 ...

  4. ( 转) Awesome Image Captioning

    Awesome Image Captioning 2018-12-03 19:19:56 From: https://github.com/zhjohnchan/awesome-image-capti ...

  5. Java内存可见性

    如果一个线程对共享变量的修改,能够被其它线程看到,那么就能说明共享变量在线程之间是可见的.如果一个变量在多个线程的工作内存中都存在副本,那么这个变量就是这几个线程的共享变量.Java内存模型(Java ...

  6. get函数

    dict={"name":"jary","age":22}print(dict.get("age")) # 通过键值找到 ...

  7. Java原生API访问MongoDB

    1.pom.xml <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java ...

  8. 英语发音规则---E字母常见的发音组合有哪些

    英语发音规则---E字母常见的发音组合有哪些 一.总结 一句话总结:很好记的e和5个元音字母的组合,加一个非e开头的ie e:开音节 /i:/  eve /i:v/ n. 夏娃----闭音节 /e/ ...

  9. 音乐推荐与Audioscrobbler数据集

    1. Audioscrobbler数据集 数据下载地址: http://www.iro.umontreal.ca/~lisa/datasets/profiledata_06-May-2005.tar. ...

  10. mean

    import caffe import numpy as np MEAN_PROTO_PATH = 'mean.binaryproto' # 待转换的pb格式图像均值文件路径 MEAN_NPY_PAT ...