【问题标题】:switch implementation; arm; assembler; aarch64; arm64切换实现;手臂;汇编器; aarch64; arm64
【发布时间】:2015-12-02 12:02:50
【问题描述】:

我对在 aarch64 汇编器上实现“switch”运算符的方式很感兴趣。 在 arm32 平台上,我使用了类似的东西

    ldr         pc,         [pc, ta, LSL#2]
    nop                                         // alignment
    .int        .L.case1
    .int        .L.case2
    ...
    .int        .L.caseN

但由于 64 位版本对 'pc' 寄存器的使用有很多限制,所以这种实现不再起作用了。

似乎最简单的方法是使用一对比较和分支操作,比如

cmp ta, #1
b.eq .L.case1
cmp ta, #2
b.eq .L.case2
...

但有时多达十几个案例,在到达最后一个“案例”之前会导致显着延迟。

请您分享一下如何在 aarch64 上实现快速切换的想法。

谢谢:)

【问题讨论】:

  • adr/adrp 可用于“pc相对地址计算”。

标签: performance assembly arm cpu-registers arm64


【解决方案1】:

我没有 64 位 ARM 汇编器来测试它,但我相信您会执行以下操作来实现跳转表:

    adr  x0, jmp_table
    ldr  x0, [x0, x1, LSL#3]
    br   x0

jmp_table:
    .quad .L.case1
    .quad .L.case2
    .quad .L.case3

第一条指令ADR 将标签的地址加载到寄存器中。最后一条指令BR 跳转到存储在寄存器中的地址。

如果您要创建共享库或位置无关的可执行文件,您可以尝试以下操作:

    adr  x0, jmp_table
    add  x0, x0, x1, LSL#2
    br   x0

jmp_table:
    b .L.case1
    b .L.case2
    b .L.case3

备用图片示例

    adr  x0, jmp_table
    ldr  w1, [x0, x1, LSL#2]
    add  x0, x0, x1
    br   x0

jmp_table:
    .int  .L.case1 - jmp_table
    .int  .L.case2 - jmp_table
    .int  .L.case3 - jmp_table

【讨论】:

  • 当我尝试执行此代码时,我得到“CANNOT LINK EXECUTABLE: text relocations (DT_TEXTREL) found in 64-bit ELF file”。编译和链接工作正常... objdump 显示此代码如下:“adr x4, 26ae0; ldr x4, [x4]; br x4; ...;”是的,只是“...”而不是实际地址。任何想法为什么?
  • 是的,使用了与位置无关的代码,它必须在Android 5上。谢谢罗斯
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-11
  • 2016-05-05
  • 2015-10-29
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多