arm64 macho 将标签存储在部分外部的寄存器中

arm64 macho store label in register from outside of section

我有为 Mac m1 (arm64 macho) 编译的汇编代码:

.text                                                                                                                                                  
.globl main                                                                                                                                            
.p2align        2                                                                                                                                      
main:                                                                                                                                                  
        stp     x29, x30, [sp, -16]!                                                                                                                   
        add     x29, sp, 0                                                                                                                                     mov     x2, #6                                                                                                                                 
        adrp    x1, _fmt@PAGE                                                                                                                          
        add     x1, x1, _fmt@PAGEOFF                                                                                                                   
        mov     x0, #1                                                                                                                                 
        adrp    x3, _write@PAGE                                                                                                                        
        add     x3, x3, _write@PAGEOFF                                                                                                                 
        blr     x3                                                                                                                                     
                                                                                                                                                       
        mov     w0, #0                                                                                                                                 
        ldp     x29, x30, [sp], #16                                                                                                                    
        ret                                                                                                                                            
/* end function main */                                                                                                                                
                                                                                                                                                       
.balign 8                                                                                                                                              
_fmt:                                                                                                                                                  
        .ascii "Hello\n"

失败:

final section layout:
    __TEXT/__text addr=0x100003F88, size=0x00000030, fileOffset=0x00003F88, type=1
    __TEXT/__unwind_info addr=0x100003FB8, size=0x00000048, fileOffset=0x00003FB8, type=22
    __DATA/__data addr=0x100004000, size=0x00000006, fileOffset=0x00004000, type=0
ld: ARM64 ADRP out of range (-4294979584 max is +/-4GB): from main (0x100003F88) to _write@0x00000000 (0x00000000) in 'main' from test.o for architecture arm64

我相信发生这种情况是因为 _write 指令引用了写系统调用,该系统调用直到 link 时间才可用,这意味着汇编程序不知道要放入什么_write 的地址,它被写为 0x00000000。 (有错请指正)

我错了。 (感谢@user3124812)

烦人的是,如果我调用 bl _write 而没有先将其放入寄存器,则不会发生这种情况。

例如:

.text                                                                                                                                                  
.globl main                                                                                                                                            
.p2align        2                                                                                                                                      
main:                                                                                                                                                  
        stp     x29, x30, [sp, -16]!                                                                                                                   
        add     x29, sp, 0                                                                                                                                     mov     x2, #6                                                                                                                                 
        adrp    x1, _fmt@PAGE                                                                                                                          
        add     x1, x1, _fmt@PAGEOFF                                                                                                                   
        mov     x0, #1                                                                                                                                 
        bl _write                                                                                                                                      
                                                                                                                                                       
        mov     w0, #0                                                                                                                                 
        ldp     x29, x30, [sp], #16                                                                                                                    
        ret                                                                                                                                            
/* end function main */                                                                                                                                
.data                                                                                                                                                  
.balign 8                                                                                                                                              
                                                                                                                                                       
                                                                                                                                                       
_fmt:                                                                                                                                                  
        .ascii "Hello\n" 

这有效并打印 Hello 后跟一个换行符。

为什么我不能在打印前将标签位置存储在寄存器中?它似乎适用于我的部分中的标签

未在与引用它们的代码相同的共享对象中定义的符号的值未知。因此,您必须像这样从全局偏移量 table (GOT) 加载此类地址:

adrp    x0, _write@GOTPAGE
ldr     x0, [x0, _write@GOTPAGEOFF]

这会将 _write 的地址加载到 x0 中。此类代码也可用于在与引用相同的共享对象中定义的符号,但在这种情况下,直接访问它们可能更容易。

当您直接使用 bl 调用一个函数时,链接器使调用转到过程链接 table (PLT),它持有一个跳转到实际函数的跳线。因此,直接调用有效。