如何在ARM64汇编代码中分配可写内存?



我正在努力学习ARM64。我在苹果M1上组装。

我正在尝试分配我可以写入的内存。我一直收到以下错误:

ld: Absolute addressing not allowed in arm64 code but used in '_main' referencing 'foo'

程序很简单:

// foo.s
.global _main
.align 2
_main:
ldr x0, =foo
.data
foo: .zero 8

我用这个脚本来编译它:

#!/bin/bash
as foo.s -o foo.o &&                               

ld foo.o -o foo                                    
-arch arm64                                     
-syslibroot `xcrun -sdk macosx --show-sdk-path` 
-lSystem

经过一些谷歌搜索,我尝试设置-no_pie为ld,但结果是:

ld: warning: -no_pie ignored for arm64

我不太清楚这是怎么回事。

感谢更新:这里有一个SO问题可以解释这个问题。

我应用了这个修复并编写了这个快速程序来测试它是否有效:

.global _main
.align 2
_main:
// Set x0 to the memory address of foo.
adrp x0, foo@PAGE
add x0, x0, foo@PAGEOFF
// Store 123 in foo.
mov x1, 123
str x1, [x0]
// Load the contents of foo into x2.
ldr x2, [x0]
// Exit with a status code set to foo.
mov x0, x2
mov x16, 1
svc 0
.data
foo: .zero 8

它返回退出状态123,正如我所期望的。

您在.data部分中使用.zero分配了内存。现在你只需要加载它的地址就可以访问它了。

最好编写与位置无关的代码,而不是试图禁用它。因此,与其尝试加载绝对地址,不如相对于程序计数器访问它们。

在中等大小的程序中(小于1兆字节的代码加上静态数据),可以使用

foo的地址加载到x0中。
adr x0, foo

adr指令在程序计数器pc的值上增加一个直接常数,并将结果留在目标寄存器中。汇编器和链接器可以确定adr指令的地址和foo的地址之间的差异,并将该差异编码为adr指令的直接地址。

对于更大的程序,其中地址的差异可能高达4gb左右,您使用adrp的组合来获得高位,add或带有偏移量的加载/存储。参见ARM汇编中ADRP和ADRL指令的语义是什么?

相关内容

最新更新