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中有特定的用处
我正在将一些 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中有特定的用处