GCC跳转表初始化代码生成movsxd并添加?

2023-12-21

当我在 GCC 中编译带有优化的 switch 语句时,它会设置一个像这样的跳转表,

(fcn) sym.foo 148
  sym.foo (unsigned int arg1);
; arg unsigned int arg1 @ rdi
0x000006e0      83ff06         cmp edi, 6                              ; arg1
0x000006e3      0f87a7000000   ja case.default.0x790
0x000006e9      488d156c0100.  lea rdx, [0x0000085c]
0x000006f0      89ff           mov edi, edi
0x000006f2      4883ec08       sub rsp, 8
0x000006f6      486304ba       movsxd rax, dword [rdx + rdi*4]
0x000006fa      4801d0         add rax, rdx                            ; '('
;-- switch.0x000006fd:
0x000006fd      ffe0           jmp rax                                 ; switch table (7 cases) at 0x85c

Is the MOVSXD https://c9x.me/x86/html/file_module_x86_id_206.html and ADD https://c9x.me/x86/html/file_module_x86_id_5.html最好的方法是,

movsxd rax, dword [rdx + rdi*4]
add rax, rdx

这不是和使用一样吗LEA https://c9x.me/x86/html/file_module_x86_id_153.html with displacement

lea rax, [rdx + rdi*4 + rdx]

我觉得我可能不明白这里发生了什么。RDX似乎是跳转表的开始。RDI是 switch 语句的传入参数。我们为什么要添加RDX不过两次?

这是我正在编译的 switch 语句-O3,

int foo (int x) {
  switch(x) {
    //case 0: puts("\nzero"); break;
    case 1: puts("\none"); break;
    case 2: puts("\ntwo"); break;
    case 3: puts("\nthree"); break;
    case 4: puts("\nfour"); break;
    case 5: puts("\nfive"); break;
    case 6: puts("\nsix"); break;
  }
  return 0;
}

海湾合作委员会正在使用relative其跳转表中的位移(相对于表的基址),而不是绝对地址。因此跳转表本身是与位置无关的,并且在重新定位时不需要修复,例如作为加载 PIE 可执行文件或 PIC 共享库的一部分。

如果你编译-fno-pie -no-pie,gcc 可能会选择使用跳转目标表jmp [table + rdi*8]

像 x86-64 Linux 这样的目标确实支持运行时数据修复,因此可以使用简单的跳转表。但有些目标根本不支持修复,这就是 gcc 的原因-fPIC / -fpie完全避免它。这种潜在的优化是海湾合作委员会错误 84011 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84011。有关更多信息,请参阅那里的讨论。


不幸的是,gcc 使用跳转表,而不是意识到每种情况之间的唯一区别是数据,而不是代码。所以实际上它只需要查找字符串指针的表。 (如果愿意的话,可以通过相对位移来完成。)

这是一个单独的错过优化,我将其报告为错误 85585 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85585。 (这提醒我,我应该完成并发布那篇写了一半的后续文章。)

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

GCC跳转表初始化代码生成movsxd并添加? 的相关文章

随机推荐

  • 我的 iOS 8 框架是否需要自己的代码签名才能分发?

    我正在尝试将我的 iOS 8 应用程序上传到应用程序商店进行分发 我的应用程序包含使用 Xcode 6 创建的框架 我从上传工具收到以下配置文件错误 错误 ITMS 90161 配置文件无效 com auraishere AuraClien
  • BadParcelableException:解组时出现ClassNotFoundException:android.support.v4.app.FragmentManagerState

    我3天前已经迁移到SDK Android 27 1 0 并且出现了一些像这样的崩溃 我不明白为什么 它 当前 出现在 Android 8 和 6 上 BadParcelableException ClassNotFoundException
  • C++ 中的快速百分位数

    我的程序计算风险价值指标的蒙特卡罗模拟 为了尽可能简化 我有 1 simulated daily cashflows 2 to get a sample of a possible 1 year cashflow I need to dra
  • Angularjs 自动为正斜杠添加前缀

    如果我点击网址说 www xyz com home route 1 AngularJS 自动将其重定向到 www xyz com home route 1 也就是说 它在路由前面加上前缀 正斜杠 为什么会发生这种情况 我怎样才能阻止它这样做
  • JavaScript 是一种按引用传递还是按值传递的语言?

    基本类型 数字 字符串等 按值传递 但对象是未知的 因为它们都可以按值传递 在这种情况下 我们认为保存对象的变量实际上是对对象的引用 对象 和按引用传递 当我们认为对象的变量保存对象本身时 尽管最后并不重要 但我想知道呈现传递约定的参数的正
  • CodeIgniter关闭自动路由?

    是否可以关闭 CodeIgniter 中的自动路由 并让它仅在存在该请求的路由时处理请求 谢谢 请记住戴尔的解决方案 route any some default controller 1 仅适用于单段 URL 例如 example com
  • Puppeteer 查找阴影元素列表并获取 ElementHandles 列表

    我正在运行 Node 12 和 Puppeteer 2 2 1 两者现在都无法升级 挑战是在阴影根中找到 DOM 元素并将它们传递给我的主类的另一个函数 此外 我正在抓取不同的网站 因此代码必须动态查找隐藏的根 使用page or page
  • 如何在java中将字符串数组拆分为小块数组?

    以下是需要帮助的代码片段示例 Example 1 2 3 4 5 如果块大小是1 1 2 3 4 5 如果块大小是2 1 2 and 3 4 and 5 如果块大小是3 1 2 3 and 4 5 如果块大小是4 1 2 3 4 and 5
  • 在 R 中使用plot()时如何摆脱网格?

    因此 我使用 R 通过 Vegan 包执行 DCA 去趋势对应分析 每次绘制结果时 我都会在图中间得到一个网格 我想摆脱它 这是我的代码 dca lt decorana dados plot dca type n ann FALSE ori
  • 在React中添加长按事件

    有没有办法添加长按React Web 应用程序中的事件 我有地址列表 长按任何地址时 我想触发事件来删除该地址 然后出现一个确认框 我创建了一个代码沙箱 https codesandbox io s uselongpress oekx2 f
  • Android 错误锁定模式监听器

    我试图找到一种方法来接收消息每次用户在其 Android 设备上插入错误的锁定模式 老实说 我不知道如何实现这一点 但我猜我应该在后台注册某种服务作为侦听器 但我应该在哪个广播公司注册我的听众 我很抱歉没有适当的术语 可能我的文本没有多大意
  • 日期和时间选择器 Google 应用程序脚本

    是否可以在 GUI 中添加日期和时间选择器框 如果没有 是否可以将两个变量 一个用于日期 选择器 另一个用于时间 数字 组合成一个变量以用作日历的开始时间变量 Thanks 这是一个使用 listBoxes 的可行解决方案 在电子表格中进行
  • Kendo UI Angular - 网格 - 如何转换值?

    如何在 Kendo Grid 上转换以下方面的值 简单的变换如 kendo grid column 字段 值 大写 不起作用 翻译 国际化 再次kendo grid column 字段 值 翻译 不起作用 将类型从整数更改为字符串 以便可以
  • 为什么我会收到此回溯错误?

    这是我得到的错误 Traceback most recent call last File dwload py line 9 in
  • 如何统计数组中连续重复的值?

    我有一个像这样的数组 arr array 1 1 1 2 2 3 3 1 1 2 2 3 我找到了这个功能array count values 但它将对所有相同的值进行分组并计算出现次数 而不考虑连续序列中的中断 result 1 5 re
  • 从 R 中的 apply() 函数返回多个值

    我想从 apply 函数返回多个值并将它们放在 R 中的单独列中 但我不断收到错误 我想做的是 experiments result1 experiments result2 experiments result3 lt apply exp
  • 在 Firebase Hosting SPA + 2 个子文件夹 firebase.json 上配置重定向

    我有一个公共文件夹 例如 public index html landing index html membership index html public index html 是一个 SPA 因此每个对 的请求都应该重写为 index
  • QML屏幕方向锁定

    我需要将屏幕锁定到我正在制作的 Android 应用程序的特定方向 QML 有没有办法做到这一点 谷歌没有给我任何答案 我正在使用 Qt 5 2 您基本上可以使用Screen orientation属性仅供阅读 详细信息请参见以下示例 ht
  • Javascript 中的 HTML 格式化程序

    我一直在寻找一个 HTML 格式化程序来与我正在做的项目结合起来 我需要用 Javascript 编写它 因为我希望在客户端完成格式化 问题是 我尝试过的一些方法效果不佳 例如 http www davidpirek com blog ht
  • GCC跳转表初始化代码生成movsxd并添加?

    当我在 GCC 中编译带有优化的 switch 语句时 它会设置一个像这样的跳转表 fcn sym foo 148 sym foo unsigned int arg1 arg unsigned int arg1 rdi 0x000006e0