反汇编一个简单的C程序

news2024/12/26 1:06:18

基于最简单的代码示例,一步步分析每一段汇编代码,对于堆栈变化

一、编译C代码

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

编译

gcc -S -o main.s main.c -m32

得到汇编代码

g:
    pushl   %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %eax
    addl    $3, %eax
    popl    %ebp
    ret
 f:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    8(%ebp), %eax
    movl    %eax, (%esp)
    call    g
    leave
    ret
main:
    pushl   %ebp
    movl    %esp, %ebp
    subl    $4, %esp
    movl    $8, (%esp)
    call    f
    addl    $1, %eax
    leave
    ret

二、关键信息

%ebp:栈帧基址,用于指向当前函数的栈帧基址,使得函数内部可以方便地访问参数和局部变量。
%esp:栈顶指针,始终指向当前栈顶的位置
%eax:寄存器
leave:恢复调用者的栈帧

movl %ebp, %esp
popl %ebp

ret:将 %eax 中的值作为返回值。

三、压栈出栈详细步骤

第一步:进入main函数

pushl %ebp:将基指%ebp 压入栈,保存上一层栈帧基址
堆栈内容

[调用者的 %ebp]

movl %esp, %ebp:将当前栈顶(%esp)存入 %ebp,设定新的栈帧基址
[调用者的 %ebp]

subl $4, %esp:栈顶指针%esp向下移动 4 字节,为局部变量分配空间

[调用者的 %ebp]
[局部变量空间:4字节]

movl $8, (%esp):将立即数 8 压入栈顶,为 f 函数调用提供参数

[调用者的 %ebp]
[参数 x = 8]

call f:调用 f,请看f的堆栈变化,将返回值存入 %eax,栈在跳转到 f 时变化

addl $1, %eax
leave
ret

第二步:f 函数堆栈变化

pushl %ebp:保存调用者的 %ebp 到栈中

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]

movl %esp, %ebp:设置新的栈帧基址,将%esp赋给%ebp

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]

subl $4, %esp:为局部变量分配 4 字节的栈空间

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间:4字节]

movl 8(%ebp), %eax:将%ebp的值 x(即 8)加载到 寄存器%eax
movl %eax, (%esp):将 %eax(x = 8)压入栈,为 g 函数调用提供参数

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间]
[参数 x = 8]

call g:调用 g,栈跳转到 g 的堆栈变化,可以获得%eax=11

leave
ret

第三步:g 函数堆栈变化

pushl %ebp:保存调用者的 %ebp

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间]
[参数 x = 8]
[f 的 %ebp]

movl %esp, %ebp:设置新的栈帧基址 堆栈内容不变

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间]
[参数 x = 8]
[f 的 %ebp]

movl 8(%ebp), %eax:从栈中取出参数 x(8),存入 %eax
addl $3, %eax:将 3 加到 %eax,计算 x + 3 = 8 + 3 = 11

popl %ebp:恢复调用者的 %ebp,清理当前栈帧 %ebp。

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间]
[参数 x = 8]

ret:返回调用者,%eax 中的值 11 作为返回值,看回f

第四步:回到 f 函数堆栈变化

Call g :返回值 11 存入 %eax,并释放掉x,恢复调用者的栈帧

[调用者的 %ebp]
[参数 x = 8]
[main 的 %ebp]
[局部变量空间]

leave:恢复调用者的栈帧。

[调用者的 %ebp]
[参数 x = 8]

ret:返回调用者,%eax 中的值 11 作为返回值

第五步:回到 main 函数堆栈变化

call f 返回:f 返回值 11 存入 %eax。

[调用者的 %ebp]

addl $1, %eax:将 1 加到 %eax 中,计算 f(8) + 1 = 11 + 1 = 12。
leave:恢复调用者的栈帧。

堆栈内容为空

ret:返回调用者,%eax 中的值 12 作为程序最终返回值。

最终结果:程序返回值为 12,存储在寄存器 %eax 中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2265548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Xcode 16 编译弹窗问题、编译通过无法,编译通过打包等问题汇总

问题1:打包的过程中不断提示 :codesign 想要访问你的钥匙串中的密钥“develop 或者distribution 证书” 解决:打开钥匙串,点击证书---显示简介---信任----改为始终信任 (记住 :不能只修改钥匙的显示简介的…

RabbitMQ中的Topic模式

在现代分布式系统中,消息队列(Message Queue)是实现异步通信、解耦系统组件的重要工具。RabbitMQ 是一个广泛使用的开源消息代理,支持多种消息传递模式,其中 Topic 模式 是一种灵活且强大的模式,允许生产者…

OpenEuler 22.03 安装 flink-1.17.2 集群

零:规划 本次计划安装三台OpenEuler 22.03 版本操作系统的服务器,用于搭建 flink 集群。这里使用flink1.17.2 的原因,是便于后续与springboot的整合 服务器名IP地址作用其他应用flink01192.168.159.133主jdk11、flink-1.17.2flink02192.168.…

国标GB28181公网直播EasyGBS与国标GB28181协议融合,助力应急救援指挥无线视频监控系统建设

随着信息技术的飞速发展,视频监控领域正经历从传统安防向智能化、网络化安防的深刻转变。在这一转变过程中,国标GB28181协议以其强大的功能和广泛的应用场景,成为了公共安全视频监控联网系统的核心标准。 应急救援指挥系统要求能够迅速响应各…

VisionPro开发使用交互反馈系统(Affordance System)

XR Interaction Toolkit 提供了一个affordance system 可供性系统,使用户能够创建对交互状态的视觉和听觉反馈。一般的信息流从向Affordance State Provider场景中添加一个(通常是可交互的)并将其指向我们要监视其交互状态的可交互对象开始。…

SpringCloud 入门(4)—— 网关

上一篇:SpringCloud 入门(3)—— Nacos配置中心-CSDN博客 Spring Cloud Gateway 作为 Spring Cloud 生态系统的一部分,主要在微服务架构中充当 API 网关的角色。它提供了统一的入口点来处理所有的 HTTP 请求,并将这些请…

在linux系统的docker中安装GitLab

一、安装GitLab: 在安装了docker之后就是下载安装GitLab了,在linux系统中输入命令:docker search gitlab就可以看到很多项目,一般安装第一个,它是英文版的,如果英文不好可以安装twang2218/gitlab-ce-zh。 …

vscode打开下一个文件的时候上一个文件会关闭

解决方法: 你可以通过设置 workbench.editor.enablePreview 来控制在 VS Code 中打开文件时是否会关闭上一个文件。将其设置为 false 可以防止这种行为。 {"workbench.editor.enablePreview": false } 在设置编辑器中显示 "workbench.editor.enab…

PostgreSQL编译安装教程

下载安装 1.在家目录创建一个文件夹放下载安装包 mkdir softwarecd software 2.下载文件压缩包 wget https://ftp.postgresql.org/pub/source/v16.0/postgresql-16.0.tar.gz 3.解压 tar -xzvf postgresql-16.0.tar.gz 4.编译 在software/postgresql-16.0下 cd software…

访谈积鼎科技总经理:国产CFD软件发展与未来趋势展望

傅彦国,上海积鼎信息科技有限公司创始人 记者:请傅总介绍下我国流体仿真行业的发展现状是怎样的? 傅彦国:自2018年政府加大了对核心技术自主研发的支持力度,国产CFD软件逐渐步入发展正轨。 首先,从市场规…

重温设计模式--代理模式

文章目录 定义UML图代理模式主要有以下几种常见类型:代理模式涉及的主要角色有:C 代码示例 定义 代理模式(Proxy Pattern)属于结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。 通过引入代理对象&am…

R语言数据分析案例46-不同区域教育情况回归分析和探索

一、研究背景 教育是社会发展的基石,对国家和地区的经济、文化以及社会进步起着至关重要的作用。在全球一体化进程加速的今天,不同区域的教育发展水平呈现出多样化的态势。这种差异不仅体现在教育资源的分配上,还表现在教育成果、教育投入与…

uni-app使用组件button遇到的问题

在HBuilder X工具中新建一个空白项目, 1、新建一个about页 然后在pages.json文件里加上路由 2、然后看下导航的方法,发现找不到navigateTo方法 参考:button | uni-app官网 第3行和第4行的代码倒是没问题的,第5行的代码有问题执行…

git自己模拟多人协作

目录 一、项目克隆 二、多人协作 1.创建林冲仓库 2.协作处理 3.冲突处理 三、分支推送协作 1.创建develop分支 2.发现git push无法把develop推送到远程 ​编辑 3.本地的分支推送到远程分支 四、分支拉取协作 五、远程分支的删除 远程仓库用的gitee 一、项目克隆 …

基于springboot+vue实现的卷烟营销统计分析系统 (源码+L文+ppt)4-129

摘 要 卷烟行业的快速发展使得卷烟营销统计分析系统成为了一个必不可少的工具。基于Java的卷烟营销统计分析系统旨在提供高效、准确和便捷的适用卷烟营销服务。本文讲述了基于java语言开发,后台数据库选择MySQL进行数据的存储。该软件的主要功能是进行卷烟营销统计…

解析CGI(通用网关接口)技术

在互联网技术飞速发展的今天,CGI(Common Gateway Interface,通用网关接口)作为一种常见的服务器端脚本技术,依然在许多老旧网站和小型网站中广泛使用。尽管如今有许多更现代的技术替代了CGI,但它仍然是理解…

OPPO C++面试题及参考答案

五层协议每层包含的协议 在计算机网络的五层协议体系结构(自下而上为物理层、数据链路层、网络层、传输层和应用层)中,各层包含多种协议。 物理层主要负责在物理介质上传输原始的比特流,包括像 RJ - 45 接口标准等物理接口规范&am…

OpenAI 普及 ChatGPT,开通热线电话,近屿智能深耕AI培训

12月19日,在OpenAI直播活动的第10天,宣布允许用户通过电话或WhatsApp与ChatGPT进行交互。并在美国推出 ChatGPT 热线电话,用户拨打后可与 ChatGPT 进行语音对话。 这项服务的一个亮点在于它兼容各种类型的通信设备——不论是现代智能手机如iP…

四种电子杂志制作软件

​大家好,今天给大家种草四种超级实用的电子杂志制作软件。无论你是专业出版人士,还是业余爱好者,这四款软件都能帮助你轻松制作出精美的电子杂志。让我们一起来看看吧! 1.FLBOOK FLBOOK是一款在线仿真翻页制作H5电子画册&#x…

idea配置

2024.3 idea 重装idea启动失败样式常用插件 重装idea启动失败 1、检查环境变量,是否已设置 2、检查安装目录下,或对应的环境变量对应的路径文件下 是否有javaagent,可先移除或者检查配置是否正确 样式 1、展示上方工具栏 2、展示内存使用…