AArch64 Mach-O汇编:如何将标签定义放入.bss段并获取符号地址到寄存器
Mach-O AArch64 汇编中正确使用.bss段缓冲区的方法
问题原因
你遇到的「unknown AArch64 fixup kind」错误,根源在于adr指令的特性限制:它只能生成相对于当前指令的PC相对偏移地址,仅能访问和当前代码(.text段)处于同一加载区域的符号。而Mach-O的.bss段是独立的零初始化数据段,和.text段不在同一内存区域,因此adr无法正确解析buffer的地址,导致链接时出现修复错误。
解决方案
在Mach-O AArch64环境下,需要使用支持跨段访问的地址加载方式,推荐两种可行方法:
方法1:使用ldr指令加载绝对地址
直接用ldr X1, =buffer加载.bss段中buffer的绝对地址,汇编器会自动处理地址重定位逻辑:
.global _start .align 8 _start: mov X0, #0 ldr X1, =buffer // 替换原有的adr指令 mov X2, #128 mov X8, #63 // AArch64 macOS系统调用号:read svc #0 mov X0, #1 mov X2, #5 // 注:此处固定输出5字节,实际可改用read的返回值(存于X0)作为输出长度 mov X8, #64 // AArch64 macOS系统调用号:write svc #0 mov X0, #0 mov X8, #93 // AArch64 macOS系统调用号:exit svc #0 .section .bss .align 8 // 建议给bss段的buffer添加对齐,符合AArch64内存规范 buffer: .skip 128
方法2:使用adrp + add组合(AArch64大地址访问标准方式)
adrp加载符号所在页面的基地址,再通过add补充页内偏移,适合大地址空间场景:
.global _start .align 8 _start: mov X0, #0 adrp X1, buffer add X1, X1, :lo12:buffer // 组合加载完整的buffer地址 mov X2, #128 mov X8, #63 svc #0 // 后续write、exit代码与上方示例一致
额外注意事项
- 你提供的编译命令存在笔误:
as as -g hello.s应改为as -g hello.s -o hello.o,修正后的完整编译命令:as -g hello.s -o hello.o && ld -o hello.exec hello.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64 - 当前代码中
write的输出长度固定为5字节,若要完全实现print(input())的逻辑,可利用read系统调用的返回值(存储在X0寄存器中)作为动态输出长度,避免截断或冗余输出。
内容的提问来源于stack exchange,提问作者Mmakabaka1880
相关产品推荐
相关产品推荐

