gpt4 book ai didi

c - 为内联汇编创建常量池的正确方法是什么?

转载 作者:太空狗 更新时间:2023-10-29 17:25:03 25 4
gpt4 key购买 nike

问题是在 C 函数内部我有一个内联汇编。有点像

  ldr r7, =0xdeadbeef
svc 0

如果没有显式创建文字池(就是这种情况),汇编器在翻译单元的末尾创建一个。通常这很好,但如果翻译单元原来真的很大,这是行不通的,因为文字池距离 ldr 指令太远。

所以,我想知道处理该问题的最佳方法是什么。最明显的方法是在内联程序集中手动创建文字池:

  ldr r7, =0xdeadbeef
svc 0
b 1f
.ltorg
1:

或者

  ldr r7, 1f
svc 0
b 2f
1:
.word 0xdeadbeef
2:

不幸的是,由于冗余分支,这会导致次优代码操作说明。我不希望汇编程序足够聪明以找到合适的在函数中放置常量池。我想做的是在函数末尾创建一个常量池。有什么办法可以告诉编译器 (gcc) 在函数的末尾 创建文字池?

PS 我最终使用了 movw/movt 对而不是常量池。尽管,首先,movw/movt 解决方案的可移植性略低于文字池,并且,其次,我只是想知道是否可以在内联汇编中使用常量池既可靠又高效。


更新: 那么,处理这个问题的最佳方法是什么?

强制工具链在可以放置的函数之后创建一个常量池该函数在单独的代码部分中。它之所以有效,是因为在翻译单元的末尾,汇编程序会生成每个部分都有单独的常量池。

不过,事实上,最好的方法是避免将常量加载到寄存器中内联汇编。最好让编译器来做。就我而言,我最终写了一个类似的代码

register int var asm("r7") = 0xdeadbeef;
asm volatile("svc 0\n" :: "r" (var));

最佳答案

您可以使用 -ffunction-sections 并根据 query on -ffunction-section , 使用 ld --gc-sections 删除未使用的代码。

有明显的分割文件。

一个可行的解决方案是使用带有 unused 注释的 naked 函数,因为它从未被调用过。在这里放置一个 .ltorg 并将两个函数放在一个特殊的部分; .text.ltorg_kludge 例如。链接器脚本应使用 .text* 并将相同子部分中的函数放在一起。在某些方面,这就像拆分文件,因为编译器将尝试内联 static 函数。

您可以依赖编译器发出在没有特殊部分的源代码中遇到的函数。但是,我不确定这是标准情况还是偶发情况。编译器可以通过在调用层次结构的某些 DAG 排序中发出函数来更好地优化。


旁白:由于缓存效应,movw/movt 效率更高。它还适用于 ARMv6 和更高版本的 Thumb2 代码。我认为可移植性不是什么大问题(因为内联汇编程序不可移植,您可能更喜欢性能而不是可移植性),但这个问题与 ARMv4/5 用户相关。


我调查了来自 gcc machine constraintsR 约束的使用,

R
      An item in the constant pool

但是,一个 sample with gcc-4.8给出一个错误不可能的约束。使用诸如 C 之类的替代字母也会给出相同的错误消息。检查source contraints.md似乎表明 R 约束是仅文档功能。不幸的是,这听起来是为了解决这个问题而设计的。

可以让编译器加载值,但这可能不是最优的,具体取决于 inline 汇编器。例如,

  asm(" add %0, %0, %1\n" : "+r" (0xdeadbeef) : "r" (0xbaddeed0));

关于c - 为内联汇编创建常量池的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28833189/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com