Apple M1 ARM64汇编:ADRP/ADD/LDR加载数据超出预期问题排查
ARM64汇编读取.data段数据异常的原因与解决办法
问题原因
你用.word伪指令定义的var1和var2是**32位(4字节)**数据,但读取时使用的ldr X1, [X0]是64位加载指令,会从内存中一次性读取8字节内容。由于var1和var2在.data段中连续存放,读取结果自然会把var1的4字节和相邻var2的4字节拼接成一个64位值——也就是你看到的0x0000000600000005,其中高32位是var2的6,低32位是var1的5。
解决办法
有两种直接可行的修复方式:
方式一:使用32位加载指令
既然数据本身是32位,就对应使用32位寄存器的加载指令ldr W1, [X0],这样只会读取4字节数据,得到正确的0x00000005。修改后的代码片段:
// Get the value from the address memory stored on X0 register. ldr W1, [X0] // 用32位W寄存器代替64位X寄存器
方式二:定义64位数据
如果需要保持用64位寄存器读取的习惯,把.word改成.dword(64位数据伪指令)即可,这样每个变量会占用8字节内存,相邻变量不会被意外读取。修改后的.data段:
.data var1: .dword 5 var2: .dword 6
相关代码与调试信息
原代码
.global _start _start: mov x0, #0 mov x1, #0 // In this first part we load data from memory. // ------------- // Load var1 from the memory, and set its address to X0 register. adrp X0, var1@PAGE // address of var1 word 4k page add X0, X0, var1@PAGEOFF // offset to var1 within the page // Get the value from the address memory stored on X0 register. // When using `ldr` with brackets loads the actual value // similar to dereferencing a pointer. ldr X1, [X0] // In this second part we update data from memory. // ------------- // Set 3 to the X2 register. mov X2, #3 // <--- This is the line 38 where I add a breakpoint // Load the memory address for the vaX2 data variable. adrp X3, var2@PAGE add X3, X3, var2@PAGEOFF // Store X2 register value to the memory address on the X3 register. str X2, [X3] // Exit program mov X0, 0 // 0 status code mov X16, #1 svc #0x80 .data var1: .word 5 var2: .word 6
编译命令
as lesson03.s -g -o lesson03.o ld lesson03.o -o lesson03 -l System -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
调试过程
lldb lesson03 (lldb) b lesson03.s:38 Breakpoint 1: where = lesson03`start + 20, address = 0x0000000100003f8c (lldb) run (lldb) re read x1 x1 = 0x0000000600000005
内容的提问来源于stack exchange,提问作者maxcnunes
相关产品推荐
相关产品推荐

