了解堆栈对齐强制

2023-11-22

考虑以下 C 代码:

#include <stdint.h>

void func(void) {
   uint32_t var = 0;
   return;
}

未优化的(即:-O0选项)GCC 4.7.2为上述代码生成的汇编代码是:

func:
    pushl %ebp
    movl %esp, %ebp
    subl $16, %esp
    movl $0, -4(%ebp)
    nop
    leave
    ret

根据堆栈对齐要求 of the 系统V ABI,堆栈必须在每个之前对齐 16 个字节call指令(堆栈边界当不使用选项更改时,默认为 16 字节-mpreferred-stack-boundary)。因此,结果为ESP modulo在函数调用之前 16 必须为零。

考虑到这些堆栈对齐要求,我假设在执行之前以下堆栈的状态表示leave指令正确:

Size (bytes)       Stack          ESP mod 16      Description
-----------------------------------------------------------------------------------

             |     . . .      |             
             ------------------........0          at func call
         4   | return address |
             ------------------.......12          at func entry
         4   |   saved EBP    |
     ---->   ------------------........8          EBP is pointing at this address
     |   4   |      var       |
     |       ------------------........4
 16  |       |                |
     |  12   |                |
     |       |                |
     ---->   ------------------........8          after allocating 16 bytes

考虑到堆栈的这种表示形式,有两点让我困惑:

  1. var显然在堆栈上没有与 16 字节对齐。这个问题似乎与我读到的内容相矛盾在这个答案中 to 这个问题(重点是我自己的):

    -mpreferred-stack-boundary=n编译器试图保留的地方堆栈上的项目对齐 to 2^n.

    就我而言-mpreferred-stack-boundary未提供,因此默认设置为 4(即:2^4=16 字节边界)GCC 文档的这一部分(我确实得到了相同的结果-mpreferred-stack-boundary=4).

  2. 在堆栈上分配 16 个字节的目的(即:subl $16, %esp指令)而不是只分配 8 个字节:分配 16 个字节后,堆栈既不会按 16 字节对齐,也不会节省任何内存空间。通过仅分配 8 个字节,堆栈将按 16 字节对齐,并且不会浪费额外的 8 个字节。


看着-O0生成机器代码通常是徒劳的。编译器将以最简单的方式发出任何有效的结果。这通常会导致奇怪的伪影。

栈对齐仅指栈帧的对齐。它与堆栈上对象的对齐方式没有直接关系。 GCC 将以所需的对齐方式分配堆栈上的对象。如果 GCC 知道堆栈帧已经提供了足够的对齐,那么这会更简单,但如果没有,GCC 将使用帧指针并执行显式对齐。

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

了解堆栈对齐强制 的相关文章

  • 对于所有对象类型 T 来说,sizeof(T) >=alignof(T) 总是这样吗?

    对于任何对象类型T是不是总是这样sizeof T 至少与alignof T 直观上似乎是这样 因为即使您调整对象的对齐方式 例如 struct small char c 高于通常的情况 它们的 大小 也会向上调整 以便数组中的对象之间的关系
  • 如何在程序中将自己缝合到自己的尾部,无限循环地封装 64KB 代码段?

    如果指令的顺序执行经过偏移量 65535 则8086将从同一代码段中的偏移量 0 处获取下一个指令字节 接下来的 COM 程序利用这一事实 不断将其整个代码 总共 32 个字节 缝合到自己的尾部 环绕在 64KB 代码段中 你可以称之为二元
  • 在 C++17 中使用 成员的链接错误

    我在 Ubuntu 16 04 上使用 gcc 7 2 并且需要使用 C 17 中的新文件系统库 尽管确实有一个名为experimental filesystem的库 但我无法使用它的任何成员 例如 当我尝试编译此文件时 include
  • 这种没有推送寄存器的交换有多安全?

    我对汇编非常陌生 下面的代码应该通过两个不同的函数交换两个整数 首先使用swap c然后使用swap asm 但我怀疑 我是否需要push 我的意思是保存 汇编代码之前寄存器的每个值和pop稍后 就在返回之前 main 换句话说 如果我返回
  • arm-linux-gnueabi 编译器选项

    我在用 ARM Linux gnueabi gcc在 Linux 中为 ARM 处理器编译 C 程序 但是 我不确定它编译的默认 ARM 模式是什么 例如 对于 C 代码 test c unsigned int main return 0x
  • GCC的sqrt()编译后如何工作?使用哪种root方法?牛顿-拉夫森?

    只是对标准感到好奇sqrt 来自 GCC 上的 math h 我自己编码的sqrt 使用牛顿拉夫森来做到这一点 是的 我知道 fsqrt 但CPU是如何做到这一点的呢 我无法调试硬件 现代 CPU 中的典型 div sqrt 硬件使用 2
  • POD 结构或标准布局类型的成员是否保证根据其对齐要求进行对齐?

    给定一个 POD 结构 在 C 03 中 或一个标准布局类型 在 C 11 中 所有成员都有基本对齐要求 是否可以保证每个成员都根据其对齐要求进行对齐 换句话说 对于所有成员m k in m0 mn标准布局类型的 S struct S T0
  • 在 x86 程序集中存储大量布尔值的最佳方法是什么?

    最近我一直在处理充满布尔值的大型数组 目前 我将它们存储在 bss部分有一个 space指令 它允许我创建字节数组 但是 由于我只需要存储布尔值 因此我希望从数组中逐位读取和写入数据 目前 我能想到的最好方法是有一个 space指令所需存储
  • 如何使用 Bochs 运行汇编代码?

    我想使用 Bochs 作为 8086 模拟器 是否有捷径可寻 我想要的是类似 emu8086 的东西 http www emu8086 com http www emu8086 com 如果程序的初始部分适合 512 字节 并且您不介意将自
  • 为什么是 ”\?” C/C++ 中的转义序列?

    C C 中有四种特殊的非字母字符需要转义 单引号 双引号 反斜杠 和问号 显然是因为它们有特殊的含义 对于单身char 对于字符串文字 对于转义序列 但为什么是 其中之一 我今天读了教科书上的转义序列表 我意识到我已经never逃脱了 以前
  • 高效memcspn

    有谁知道 memcspn 函数的有效实现吗 它的行为应该类似于 strcspn 但在内存缓冲区中查找跨度 而不是在以 null 结尾的字符串中查找跨度 目标编译器是 VisualC 谢谢 卢卡 一种近乎最佳的实现 size t memcsp
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • NASM 中的 equ 和 db 有什么区别?

    len equ 2 len db 2 它们是否相同 产生可以用来代替的标签2 如果不是 那么每种申报表的优点或缺点是什么 它们可以互换使用吗 第一个是equate 与 C 类似 define len 2 因为它实际上并没有在最终代码中分配任
  • clang 实例化后静态成员初始化

    这样的代码可以用 GCC 编译 但 clang 3 5 失败 include
  • GCC 5 及更高版本中的 AVX2 支持

    我编写了以下类 T 来加速操作 使用 AVX2 的 字符集 然后我发现它不起作用 gcc 5 及更高版本当我使用 O3 时 谁能帮我追踪到一些编程结构 已知不适用于最新的编译器 系统 该代码的工作原理 底层结构 bits 是一个 256 字
  • 在GCC中添加父目录的包含路径

    我想将父目录中的文件包含在我正在处理的项目中 所有的头文件都在父目录中 有没有办法在命令行上使用 I 来搜索父目录中的包含而不使用绝对路径 我知道我可以使用 makefile 解决这些问题 并且我可能最终会这样做 但我想知道是否有一个可以使
  • GCC 的“-Wl,option”和“-Xlinker option”语法之间有区别吗?

    我一直在查看一些配置文件 并且看到它们都被使用 尽管在不同的体系结构上 如果您在 Linux 机器上使用 GCC 将选项传递给链接器的两种语法之间有区别吗 据我所知 阅读 GCC 手册时 他们的解释几乎相同 From man gcc Xli
  • 要求编译器发出无分支/恒定时间代码

    在密码学中 任何依赖于秘密数据 例如私钥 的代码都必须在恒定时间内执行 以避免侧信道定时攻击 https en wikipedia org wiki Timing attack 目前最流行的架构 x86 64 和 ARM AArch64 都
  • 将字段中的位扩展到掩码中所有(重叠+相邻)集位的最快方法?

    假设我有 2 个名为 IN 和 MASK 的二进制输入 实际字段大小可能是 32 到 256 位 具体取决于用于完成任务的指令集 每次调用时两个输入都会改变 Inputs IN 1100010010010100 MASK 000111101
  • Intel:序列化指令和分支预测

    英特尔架构开发人员手册 http www intel com content www us en architecture and technology 64 ia 32 architectures software developer v

随机推荐

  • 两张表具有相同的列,还是一张表具有附加列?

    假设我有两个表 苹果和橙子 它们具有相同的列 只是表名不同 将其变成一个带有附加列 类型 的表 假设它称为 水果 然后存储 苹果 或 橙色 的值 是否有任何优点 缺点 编辑以澄清 创建表苹果 id 整数 权重整数 各种 varchar 25
  • Tomcat 无法找到我的 Servlet 并抛出异常,但为什么呢?

    我正在尝试进入 Java Web 开发 但似乎在 Tomcat 和一个极其简单的 servlet 方面遇到了一个奇怪的问题 每次我尝试加载应用程序时 catalina 日志都会喷出以下内容 Caused by java lang Illeg
  • 计算渐变颜色的最快方法?

    我正在制作一小部分与渐变相关的类型 函数以供将来使用 我想确保至少有两个过程 ColorBetween 和 ColorsBetween 我可能只想获取任意 2 种颜色 ColorsBetween 之间的 TColor 数组 并且我可能只需要
  • AWS SNS 是否将 apns-push-type 和 apns-priority 添加到其 iOS 推送通知标头中?

    根据Apple 的 APN 文档 从 http api 的 iOS 13 客户端开始must发送标头字段apns push type and apns priority否则请求将失败 果然 更新到 iOS 13 Beta 版的用户并没有收到
  • django staticfiles 是否跳过中间件?

    我正在运行 django 1 4 1 应用程序 我没有意识到只是包括django contrib staticfiles into INSTALLED APPS在您的设置中足以获得静态文件settings DEBUG是 True 即您不必手
  • 我的 Ubuntu 系统上有 Python,但 gcc 找不到 Python.h [重复]

    这个问题在这里已经有答案了 我在学校计算机上 所以无法安装任何东西 我正在尝试创建可以在 Python 中运行的 C 代码 看来我找到的所有文章都需要你使用 include
  • 何时使用 RSpec let()?

    我倾向于使用 before 块来设置实例变量 然后我在我的示例中使用这些变量 我最近遇到了let 根据 RSpec 文档 它用于 定义一个记忆辅助方法 该值将在同一示例中的多个调用之间进行缓存 但不会跨示例进行缓存 这与在 before 块
  • this.offset 不是点击函数中的函数

    错误在于 this offset不是一个函数 我将其记录到控制台 它是 li 我点击了元素 所以我很困惑为什么这不起作用 item click function e var this this var topx this offset to
  • 在android中反序列化JSON字符串

    我有如下所示的 JSON 字符串 Status Clear Class br name personA available 1 br name personB available 0 br name personC available 0
  • 高效删除 Django 中孤立的 m2m 对象/标签

    我有两个模型 照片和标签 通过 ManyToManyField 连接 class Photo models Model tags models ManyToManyField Tag class Tag models Model lang
  • 图表 JS 插件可根据值更改线条颜色

    我正在尝试创建一个折线图 其中线条 和点 的颜色取决于所绘制的值 例如 如果该值高于以下阈值 0 115 125 那么颜色将是 green yellow red 分别 该要求与本例中实现的要求几乎相同 https jsfiddle net
  • Linux 中的 FreeGLUT 链接问题

    我在跑步Linux 薄荷 14 1 64 位 我已经安装了以下库 台面通用开发 freeglut3 开发 libglew dev 通过apt get tool 这是我的包含内容 位于我的Main h file include
  • OpenCV imwrite 2.2 在 Windows 7 上导致异常,并显示消息“OpenCV 错误:未指定错误(无法找到指定扩展名的编写器)”

    我正在将 OpenCV 2 2 应用程序从 Unix 可以运行 移植到 Windows 7 64 位上 当调用 cv imwrite 时 我收到以下异常 OpenCV 错误 未知函数中出现未指定错误 无法找到指定扩展名的编写器 文件 hig
  • OpenGL 中的低分辨率模仿旧游戏

    我有兴趣知道如何在 OpenGL 中模仿旧游戏 如 Atari 2600 的低分辨率来制作 fps 游戏 我想最好的方法是将缓冲区写入纹理 放在四边形上并将其显示到屏幕分辨率 看看http www youtube com watch v E
  • 用python进行曲线拟合

    我正在尝试适应一些数据和东西 我知道有一个简单的命令可以使用 python numpy matplotlib 来执行此操作 但我找不到它 我认为这就像 popt popc numpy curvefit f x where popt是参数f
  • Flask 会话不会持续

    我最近部署了我的第一个 Flask 应用程序 实际上是第一个 Web 应用程序 我遇到的一个问题与会话有关 但没有运气追踪到 我正在做的是当用户登录时我设置session user user id发生的情况是 在发出涉及该会话密钥的请求时
  • Mac OS X 上的 Java Swing GUI

    您是否曾尝试使用 Swing 但最终却因为它无法实现您想要的功能而改变课程 我对 Swing 还很陌生 5 年前才将它用于学校项目 但似乎 Swing 在提供更原生的外观和感觉方面已经取得了很大的进步 以至于我正在考虑使用它来开发Mac O
  • facebook Uncaught OAuthException:必须使用活动访问令牌来查询有关当前用户的信息

    我一直在努力找出这是怎么回事 我的脚本运行良好一段时间 然后突然一半停止了 我正在访问 api 并取回访问令牌 有了访问令牌 我就可以很好地访问用户的公共信息 但是 当我尝试将信息发布到他们的 FB 帐户时 我收到此错误 Fatal err
  • 当我重画太多时停止摆动

    我正在制作一个带有瓷砖地图的角色扮演游戏 为了生成图块地图 我循环遍历一个二维数组 但这意味着当我重新绘制时 我每次都必须这样做 如果我重画太多 屏幕就会闪烁 我怎样才能阻止这种情况 package sexyCyborgFromAnOthe
  • 了解堆栈对齐强制

    考虑以下 C 代码 include