assembly - 如何在 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
经过一番谷歌搜索后,我尝试设置-no_pie
ld 但这会导致:
ld: warning: -no_pie ignored for arm64
我不确定发生了什么。
谢谢
更新:这里有一个问题可以解释这个问题。
我应用了该修复程序并编写了这个快速程序来测试它是否有效:
.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
或者使用带有偏移量的加载/存储。请参阅ARM 汇编中 ADRP 和 ADRL 指令的语义是什么?
推荐阅读
- javascript - 如何读取/更新从 Firebase 转换为 JSON 的对象实例
- android - 项目无法在回收站视图中设置
- javascript - 上一个功能结束后继续功能
- java - 关于java中的字符串拆分方法
- javascript - 类型“{}”缺少来自“匹配”类型的以下属性
':参数、isExact、路径、url - python-3.x - 如何在 vscode 中更改可访问 git 的默认 python 包?
- python - 按值标准和键标准排序后从字典中选择键
- dart - 客户端断开连接时未调用 dart io websocket
- azure-cosmosdb - 如何选择索引键,我们是否应该考虑来自 GROUPBY 的键也与 WHERE 键或仅与 WHERE 键一起使用?
- google-cloud-spanner - 二级索引在创建时是否会锁定任何内容?