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

2024-06-06 09:32

本文主要是介绍通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

刘子健 

原创作品转载请注明出处

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




对一下代码进行反汇编分析:

int g(int x)
{return x + 42;
}int f(int x)
{return g(x);
}int main(void)
{return f(42) + 42;
}


我的主机是64位的Linux,所以使用的反汇编代码也是64-bits的.

	.file	"2015_03_01.c".text.globl	g.type	g, @function
g:
.LFB0:.cfi_startprocpushq	%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq	%rsp, %rbp.cfi_def_cfa_register 6movl	%edi, -4(%rbp)movl	-4(%rbp), %eaxaddl	$42, %eaxpopq	%rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE0:.size	g, .-g.globl	f.type	f, @function
f:
.LFB1:.cfi_startprocpushq	%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq	%rsp, %rbp.cfi_def_cfa_register 6subq	$8, %rspmovl	%edi, -4(%rbp)movl	-4(%rbp), %eaxmovl	%eax, %edicall	gleave.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE1:.size	f, .-f.globl	main.type	main, @function
main:
.LFB2:.cfi_startprocpushq	%rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq	%rsp, %rbp.cfi_def_cfa_register 6movl	$42, %edicall	faddl	$42, %eaxpopq	%rbp.cfi_def_cfa 7, 8ret.cfi_endproc
.LFE2:.size	main, .-main.ident	"GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"

反汇编得到的代码里面有很多提示信息,提示信息以 . 开头,程序执行时这些提示信息不是指令,我们在这个反汇编样例里面可以精简代码,把这些提示信息删除.有些信息不能剔除,这些信息是编译器必须的,否则你过不了编译链接.

下面是精简后的反汇编代码:以下代码可以通过 gcc ./2015_03_01.s -o ./a.out

	.text.globl	g.type	g, @function
g:pushq	%rbpmovq	%rsp, %rbpmovl	%edi, -4(%rbp)movl	-4(%rbp), %eaxaddl	$42, %eaxpopq	%rbpret.size	g, .-g.globl	f.type	f, @function
f:pushq	%rbpmovq	%rsp, %rbpsubq	$8, %rspmovl	%edi, -4(%rbp)movl	-4(%rbp), %eaxmovl	%eax, %edicall	gleaveret.size	f, .-f.globl	main.type	main, @function
main:pushq	%rbpmovq	%rsp, %rbpmovl	$42, %edicall	faddl	$42, %eaxpopq	%rbpret.size	main, .-main



关于基本汇编指令的分析,我之前有笔记,可以去看这里:

http://blog.csdn.net/cinmyheart/article/details/25558911

我们这里着重分析反汇编代码:

g: , f:, main: 均用来指示函数的入口.

对于函数main.

首先压栈,pushq 指令将rsp寄存器的值减去一个指针长度,在64-bits机器上即8byte,然后将 rbp寄存器的值写入到rsp指向的地址处.

movq %rsp, %ebp指令则将rsp寄存器的值赋值给rbp寄存器.这样一来,属于main函数的栈区域便构建好了.

接着movl 把立即数42赋值给寄存器edi, 然后call指令调用函数f.函数f的返回值会储存在eax寄存器中,等待f调用完之后,会把eax寄存器的值和立即数42相加,并储存在eax寄存器中.最后把rbp寄存器处的值弹栈.然后ret指令返回.

---------------------------------------------------------------------------------

call  f 

指令就相当于

push %eip #把当前指令指针寄存器压栈,然后跳转到f处
jump f

---------------------------------------------------------------------------------

ret 指令就相当于

popl %eip  #把当前esp寄存器指向地址处的值,赋值给eip

然后把esp寄存器的值减去一个指针长度,即8-byte

---------------------------------------------------------------------------------



看看函数f都干了神马.

还是和上面介绍main函数一样的"老规矩",构建函数f的堆栈,

pushq %rbp

movq %rsp, %rbp

接着使用subq $8, %rsp把rsp寄存器的值减去8.

接着把edi寄存器的值赋值给rbp寄存器指向地址处减去4byte的地址处

紧接着,把这个地址处的值赋值给eax寄存器.

把eax寄存器的值又赋值给edi寄存器(其实我想说,这不是吓折腾么...这编译器啊..这期间edi寄存器的值没变)



然后调用函数g

一句话概括就是把edi寄存器的值加上42赋值给eax寄存器,然后返回.(不改变edi寄存器的值)




阐明自己对“计算机是如何工作的”理解:

对于规范化后的程序指令,逐一的对程序指令进行"解释处理".不同的CPU,可能有不同的汇编指令集,比方说Intel -- X86 /X64平台,ARM平台,PowerPC等等,但是他们最基本的的思想都是近似的--冯诺依曼体系结构.

数字计算机的数制采用二进制;计算机应该按照程序顺序执行


-----------------------






这篇关于通过反汇编一个简单的C程序,分析汇编代码理解计算机是如何工作的的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1035725

相关文章

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Python主动抛出异常的各种用法和场景分析

《Python主动抛出异常的各种用法和场景分析》在Python中,我们不仅可以捕获和处理异常,还可以主动抛出异常,也就是以类的方式自定义错误的类型和提示信息,这在编程中非常有用,下面我将详细解释主动抛... 目录一、为什么要主动抛出异常?二、基本语法:raise关键字基本示例三、raise的多种用法1. 抛

基于Python实现一个简单的题库与在线考试系统

《基于Python实现一个简单的题库与在线考试系统》在当今信息化教育时代,在线学习与考试系统已成为教育技术领域的重要组成部分,本文就来介绍一下如何使用Python和PyQt5框架开发一个名为白泽题库系... 目录概述功能特点界面展示系统架构设计类结构图Excel题库填写格式模板题库题目填写格式表核心数据结构

github打不开的问题分析及解决

《github打不开的问题分析及解决》:本文主要介绍github打不开的问题分析及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、找到github.com域名解析的ip地址二、找到github.global.ssl.fastly.net网址解析的ip地址三

python编写朋克风格的天气查询程序

《python编写朋克风格的天气查询程序》这篇文章主要为大家详细介绍了一个基于Python的桌面应用程序,使用了tkinter库来创建图形用户界面并通过requests库调用Open-MeteoAPI... 目录工具介绍工具使用说明python脚本内容如何运行脚本工具介绍这个天气查询工具是一个基于 Pyt

Ubuntu设置程序开机自启动的操作步骤

《Ubuntu设置程序开机自启动的操作步骤》在部署程序到边缘端时,我们总希望可以通电即启动我们写好的程序,本篇博客用以记录如何在ubuntu开机执行某条命令或者某个可执行程序,需要的朋友可以参考下... 目录1、概述2、图形界面设置3、设置为Systemd服务1、概述测试环境:Ubuntu22.04 带图