Linux 上的 x86 32 位汇编中的函数调用如何工作?

2024-01-11

我正在从 Jonathan Bartlett 的《Programming from ground up》一书中学习 GNU 汇编。

在讨论函数调用和堆栈的主题时,我无法理解它的工作原理。

下面是书上写的内容:

在执行函数之前,程序将函数的所有参数按照记录的相反顺序压入堆栈。然后程序发出一条调用指令,指示它希望启动哪个函数。调用指令做了两件事。首先,它将下一条指令的地址(即返回地址)压入堆栈。然后它修改指令指针(%eip)以指向函数的开头。因此,在函数启动时,堆栈看起来像这样(在此示例中,堆栈的“顶部”位于底部):

Parameter #N
...
Parameter 2
Parameter 1
Return Address <--- (%esp)

函数的每个参数都被压入堆栈,最后就是返回地址。现在函数本身还有一些工作要做。

它所做的第一件事是通过执行 Pushl %ebp 保存当前基指针寄存器 %ebp。基指针是一个特殊的寄存器,用于访问函数参数和局部变量。接下来,它通过执行 movl %esp, %ebp 将堆栈指针复制到 %ebp。这使您能够从基指针访问作为固定索引的函数参数。您可能认为可以使用堆栈指针来实现此目的。但是,在程序期间,您可以使用堆栈执行其他操作,例如将参数推送到其他函数。将堆栈指针复制到函数开头的基指针中,可以让您始终知道参数在哪里(正如我们将看到的,局部变量也是如此),即使您可能将东西推入或推出堆栈。 %ebp 始终位于函数开头的堆栈指针所在的位置,因此它或多或少是对堆栈帧的常量引用(堆栈帧由函数内使用的所有堆栈变量组成,包括参数、局部变量变量和返回地址)。

此时,堆栈如下所示:

Parameter #N <--- N*4+4(%ebp)
...
Parameter 2 <--- 12(%ebp)
Parameter 1 <--- 8(%ebp)
Return Address <--- 4(%ebp)
Old %ebp <--- (%esp) and (%ebp)

如您所见,每个参数都可以使用 %ebp 寄存器使用基指针寻址模式来访问。

我能否简要介绍一下作者在第二段之后想要讲述的内容。 我显然对 %esp、%ebp 寄存器和 %ebp 在这里工作感到困惑。 非常感谢任何帮助。


在第二个图中,有“旧%ebp

这意味着已保存%ebp值(函数保存/恢复的调用者的值)由两者都指向%esp和你的新%ebp在那时候。

你刚刚跑了push %ebp,这做到了esp -= 4并存储%ebp to (%esp)。这可以节省呼叫者的%ebp以便您稍后可以恢复它。

然后你跑了mov %esp, %ebp建立%ebp作为帧指针。所以%ebp = %esp,并且它们都指向您最后推动的东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 上的 x86 32 位汇编中的函数调用如何工作? 的相关文章

  • gcc 如何知道内联汇编中使用的寄存器大小?

    我有内联汇编代码 define read msr index buf asm volatile rdmsr d buf 1 a buf 0 c index 使用该宏的代码 u32 buf 2 read msr 0x173 buf 我发现反汇
  • 推送 64 位 intel osx

    我想将 64 位地址压入堆栈 如下所示 asm pushq 0x1122334455667788 但我得到编译错误 我只能按以下方式推送 asm pushq 0x11223344 有人可以帮助我理解我的错误吗 我是装配新手 所以如果我的问题
  • 汇编编程语言:程序仅当输入为 ESC 时退出,并在退出前要求确认(y/n),否则循环

    我只是汇编语言编程的初学者 我们的第一个任务是让程序仅在输入为 ESC 时退出 退出之前请求确认 y n 否则循环 我知道 ESC 在 ASCII 代码中具有等效值 但我对插入位置或是否需要添加更多内容感到困惑 请帮我 这是程序 model
  • 如何在 Ubuntu 14.04 LTS 中安装 ia32-libs (Trusty Tahr)

    我昨天安装了 Ubuntu 14 04 Trusty Tahr 一切看起来都还好 但是当我尝试编译一些C代码时 我遇到了以下错误 该错误似乎是由于操作系统缺乏 32 位架构支持造成的 错误输出如下 usr bin ld i386 archi
  • ARM 调用约定是否允许函数不将 LR 存储到堆栈中?

    正如标题所示 我在理解 ARM 架构的调用约定时遇到问题 特别是 我仍然很难知道当你调用子程序时 LR 寄存器会发生什么 我认为 当您进入子程序时 处理 LR 寄存器的最明显 最安全的方法是将其存储到堆栈中 但该行为没有出现在文档中 因此我
  • 使用 gdb 调试反汇编库

    在Linux和Mac OS X中可以使用strapi和next来调试应用程序而无需调试信息 在 Mac OS X 上 gdb 显示在库内部调用的函数 尽管有时会在每个 stepi 指令中推进多个汇编程序指令 在 Linux 上 当我进入动态
  • 装配中出现奇怪的字符?

    我写了以下代码 386 model small stack 100h data text db Paper 0 code start lea dx text mov ah 9h int 21h mov ah 4ch int 21h end
  • 为什么这个 C++ 包装类没有被内联掉?

    EDIT 我的构建系统出了问题 我还在弄清楚到底是什么 但是gcc产生了奇怪的结果 尽管它是 cpp文件 但是一旦我使用了g 然后它按预期工作 对于我一直遇到麻烦的事情来说 这是一个非常精简的测试用例 其中使用数字包装类 我认为会内联 使我
  • 为什么这个“std::atomic_thread_fence”起作用

    首先我想谈一下我对此的一些理解 如有错误请指正 a MFENCE在x86中可以保证全屏障 顺序一致性可防止 STORE STORE STORE LOAD LOAD STORE 和 LOAD LOAD 重新排序 这是根据维基百科 https
  • 为什么我可以使用 ret 退出 main?

    我即将弄清楚程序堆栈到底是如何设置的 我了解到用以下方式调用该函数 call pointer 实际上等同于 mov register pc programcounter add register 1 where 1 is one instr
  • 汇编指令陷阱有什么作用?

    当程序需要时 程序通常会发出软件陷阱 由操作系统提供服务 通用异常处理程序 操作系统确定陷阱的原因并做出响应 适当地 汇编指令 trap 和 BASIC 中的 TRAP 指令一样吗 答案似乎是肯定的 你能接受还是拒绝我的结论 不中断 的代码
  • 破坏/分解函数的函数

    我以前有过 here https stackoverflow com questions 4920610 c class function in assembly 已经表明 C 函数不容易用汇编表示 现在我有兴趣以一种或另一种方式阅读它们
  • x86-64 上这个语句有什么问题?

    该函数的目的是获取堆栈的起始地址 unsigned long find start void asm movq rsp eax 当我编译它时 出现错误 Error suffix or operands invalid for movq mo
  • Clang 使用 -nostdlib 生成崩溃代码

    我正在尝试为可执行文件设置自己的运行时环境 但无法使用 clang v3 4 1ubuntu1 目标 x86 64 pc linux gnu 来生成没有段错误的可执行文件 我已将问题简化为以下内容 如果我有一个文件 crt1 c 除了满足
  • 即使我确实为变量设置了初始值,数据段也没有被初始化

    我已经编写了一个代码 该代码应该生成某种数字列表 但是即使我为它们分配了初始值 我的数据段变量也没有被初始化 This is how DS 0000 looks when I run it 这是我的代码 但数据段只保留垃圾值 MODEL s
  • 在 x86 Intel VT-X 非根模式下,是否可以在每个指令边界传递中断?

    除了不将中断传送到虚拟处理器的某些正常指定条件 cli if 0 等 之外 客户机中的所有指令实际上都是可中断的吗 也就是说 当传入的硬件中断先传递给 LAPIC 然后传递给处理器时 据说会发生一些内部魔法 将其转换为虚拟中断给来宾 使用虚
  • 奇怪的 MSC 8.0 错误:“ESP 的值未在函数调用中正确保存...”

    我们最近尝试将一些 Visual Studio 项目分解为库 并且在测试项目中一切似乎都编译和构建得很好 其中一个库项目作为依赖项 然而 尝试运行该应用程序给我们带来了以下令人讨厌的运行时错误消息 运行时检查失败 0 ESP 的值未在函数调
  • 汇编基础知识:输出寄存器值

    我刚刚开始学习汇编语言 我已经陷入了 在屏幕上显示存储在寄存器中的十进制值 的部分 我使用 emu8086 任何帮助将不胜感激 model small Specifies the memory model used for program
  • 两个基本的 ANTLR 问题

    我正在尝试使用 ANTLR 来获取简单的语法并生成汇编输出 我在 ANTLR 中选择的语言是 Python 许多教程看起来非常复杂或详细阐述与我无关的事情 我真的只需要一些非常简单的功能 所以我有两个问题 将值从一个规则 返回 到另一规则
  • 为什么当大小大于 50 时,该程序花费的时间会呈指数级增长?

    所以我正在为类编写一个 ARM 汇编快速排序方法 我对大部分内容都有了解 除了复杂性没有意义 我们将其与我们制作的另一种冒泡排序方法进行比较 它对于具有 1 个参数和 10 个参数的示例表现更好 然而 我什至无法比较 100 个参数测试 因

随机推荐

  • 带有位置参数的 Git 别名

    基本上我正在尝试别名 git files 9fa3 执行命令 git diff name status 9fa3 9fa3 但 git 似乎没有将位置参数传递给别名命令 我努力了 alias files git diff name stat
  • 为什么 Apache 没有在 XAMPP 上启动 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 直到昨天 我的本地主机一切都很好 但从昨天开始 本地主机无法打开 它说 无法连接 我尝试了很多次来启动Apache on XAMPP 但它说消息忙 我
  • .NET .config 文件中 ConnectionString 元素的用途

    在中存储和读取应用程序的连接字符串有什么区别
  • 转移 PyPI 包的所有权

    As per PEP 541 https www python org dev peps pep 0541 现在可以认领废弃的 PyPI 项目 有人这样做过吗 联系谁 我尝试过dist utils 邮件列表 https mail pytho
  • Get-EventLog - 某些事件日志源缺少有效消息

    我正在使用 get eventlog 提取和过滤系统事件日志数据 我发现 get event log 无法正确返回与某些条目关联的消息 这些条目通常显示在事件日志查看器中 例如 get eventlog logname system sou
  • Python 模拟多个具有不同结果的调用

    我希望能够对特定属性函数进行多次调用 为每次连续调用返回不同的结果 在下面的示例中 我希望增量在第一次调用时返回 5 然后在第二次调用时返回 10 Ex import mock class A def init self self size
  • OpenCV 和 VS2010:致命错误 LNK1104:致命错误 LNK1104:无法打开文件“tbb_debug.lib”

    我尝试按照本指南使用 Visual Studio C 2010 安装 OpenCV 使用 Windows 7 64 位 在 Visual C 2010 Express 中安装 OpenCV 2 4 3 https stackoverflow
  • Django 独立脚本

    我正在尝试从另一个 python 脚本访问我的 Django v1 10 应用程序数据库 但遇到了一些问题 这是我的文件和文件夹结构 store store init py settings py urls py wsgi py store
  • 面向对象的设计建议

    这是我的代码 class Soldier public Soldier const string name const Gun gun string getName private Gun gun string name class Gun
  • Android:SensorManager.getRotationMatrix 和 SensorManager.getOrientation() 的算法

    要在 Android 中获取欧拉角 例如俯仰角 横滚角 方位角 的方向 需要执行以下操作 SensorManager getRotationMatrix float R float I float 重力 float 地磁 SensorMan
  • 跨站脚本注入

    我正在测试一个网络应用程序 我想写一个XSS将显示警报的脚本 Hello 我写的第一个脚本是
  • VBA Word - 带有初始文件名的另存为对话框

    我有一个 vba 宏 可以对当前文档进行一些更改 并确定应该用于该文档的文件名 如果该文档没有保存为该文件名 但应该提示用户这样做 但应该能够更改默认设置 我发现两种可能性都不完美 我需要这两种的混合 第一种方法 Application D
  • 如何使用Airflow获取并处理mysql记录?

    我需要 1 run a select query on MYSQL DB and fetch the records 2 Records are processed by python script 我不确定我应该采取什么方式 xcom 是
  • 根据使用的发电机设置 QTDIR

    我正在尝试设置一个 CMake 项目 该项目由多个静态库和一个依赖于 QT 的主要可执行文件组成 我希望在运行 cmake 构建时能够选择 MinGW 或 MSVC 构建 我最近了解到 如果满足以下条件 CMake 的 QT 特定部分将自动
  • 如何设置 NSMenuItem 操作的发送者?

    Apple 文档说传递给 NSMenuItem 操作的发送者可以设置为某个自定义对象 但我似乎不知道如何执行此操作 有没有我在文档中没有看到的方法 我不确定您指的是哪一份文档 链接会有所帮助 您可以使用 setRepresentedObje
  • 在 SQL Server 中创建相关矩阵

    我试图在 SQL Server 中获取相关矩阵 并且我的数据按以下方式存储在表中 RptLOB1 RptLOB2 Correlation AE AE 1 Bail AE 0 35 Commercial Bail 0 25 Commercia
  • K8s 失败rabbitmq-peer-discovery-k8s 集群

    我正在尝试使用 Rabbitmq peer discovery k8s 插件在 Kubernetes 上启动 RabbitMQ 集群 并且我总是只有一个 pod 运行并准备就绪 但下一个总是失败 我尝试对配置进行多次更改 这就是至少一个 P
  • Python 相当于 Java 的“Keystore”?

    Python 平台中是否有用于存储 检索加密密钥和证书的标准机制 相当于 Java 平台中的 keystore truststore PKCS12 是通用标准 Pythons from OpenSSL import crypto 处理这个通
  • 如何防止 onTapDown 在父小部件 GestureDetector 上触发?

    我有一个堆栈 可以在其中拖动多个小部件 此外 Stack 所在的容器有一个 GestureDetector 可以在 onTapDown 和 onTapUp 上触发 我希望仅当用户点击堆栈中的小部件外部时才触发这些 onTap 事件 我尝试过
  • Linux 上的 x86 32 位汇编中的函数调用如何工作?

    我正在从 Jonathan Bartlett 的 Programming from ground up 一书中学习 GNU 汇编 在讨论函数调用和堆栈的主题时 我无法理解它的工作原理 下面是书上写的内容 在执行函数之前 程序将函数的所有参数