微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我正在尝试学习 ARM64。我正在 Apple 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

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

ld: warning: -no_pie ignored for arm64

我不太确定发生了什么。

谢谢

更新:一个 SO 问题 here 解释了这个问题。

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

.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 的退出状态返回。

解决方法

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

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

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

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

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

对于较大的程序,其中地址差异可能高达 4 GB 左右,您可以使用 adrp 的组合来获取高位,并使用 add 或加载/存储抵消。见What are the semantics of ADRP and ADRL instructions in ARM assembly?

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。