LLVM ARM64 程序集:获取 symbol/label 地址?

LLVM ARM64 assembly: Getting a symbol/label address?

我正在将一些 32 位 ARM 代码移植到 64 位,但无法确定该指令的 64 位版本:

ldr  r1, =_fns

其中 _fns 是在项目其他地方的某个 C 源文件中定义的符号。

我已经尝试了以下方法,但都出现错误:

adr  x1, _fns     <== "error: unknown AArch64 fixup kind!"
adrl  x1, _fns    <== "error: unrecognized instruction mnemonic"

汇编器是iOS SDK (XCode 7.1)中的LLVM。

我注意到如果 _fns 是本地定义的(即在同一个 .S 文件中),那么 "adr x1,_fns" 可以正常工作。然而,这不是解决办法,因为 _fns 必须在 C 代码中(即在不同的翻译单元中)。

使用 LLVM ARM 汇编程序执行此操作的正确方法是什么?

如果我喂

extern char ar[];

char *f()
{
  return ar;
}

进入ELLCC (clang based) demo,我得到:

针对 ARM AArch64 的编译器的输出

    .text
    .file   "/tmp/webcompile/_3793_0.c"
    .globl  f
    .align  2
    .type   f,@function
f:                                      // @f
// BB#0:                                // %entry
    adrp    x0, ar
    add x0, x0, :lo12:ar
    ret
.Lfunc_end0:
    .size   f, .Lfunc_end0-f


    .ident  "ecc 0.1.13 based on clang version 3.7.0 (trunk) (based on LLVM 3.7.0svn)"
    .section    ".note.GNU-stack","",@progbits

adrp指令获取ar的"page"地址到x0 . adrp 的符号参数转换为符号所在的 4K 页的 21 位 PC 相对偏移量。该偏移量被添加到 PC 以获得页面的实际开始。 add指令将符号地址的低12位相加得到实际的符号地址。

该指令序列允许加载 PC +/-4GB 范围内的符号地址。

据我所知,似乎没有一种方法可以在 C 中获得类似于 32 位 ARM 的“=ar”的功能。我使用汇编语言,看起来这会起作用:

        .text
        .file   "atest.s"
        .globl  f
        .align  2
f:
        ldr     x0, p
        ret
        .align  3
p:
        .xword  _fns

这与 32 位 ARM 在幕后所做的非常相似。

我开始使用 C 版本的唯一原因是为了展示我通常如何解决这样的问题,尤其是在我对目标汇编语言不太熟悉的情况下。

这对我来说很好,xcode7.1 LLVM7.0 IOS9.1

在 32 位 arm 中
ldr r9,=JumpTab

更改为 64 位 arm

adrp x9,JumpTab@PAGE
添加 x9,x9,JumpTab@PAGEOFF

对了,你需要注意寄存器的编号,有些寄存器在arm64中有特定的用处