我有為 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
指令參考了直到鏈接時間才可用的 write syscall,這意味著匯編器不知道將什么作為地址,_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
然后是換行符。
為什么我不能在列印之前將標簽位置存盤在暫存器中?它似乎適用于我的部分中的標簽
uj5u.com熱心網友回復:
未在與參考它們的代碼相同的共享物件中定義的符號的值是未知的。因此,您必須像這樣從全域偏移表 (GOT) 加載此類地址:
adrp x0, _write@GOTPAGE
ldr x0, [x0, _write@GOTPAGEOFF]
這會將 的地址加載_write
到x0
. 此類代碼也可用于在與參考相同的共享物件中定義的符號,但在這種情況下,直接訪問它們可能更容易。
當您直接使用 呼叫函式時bl
,聯結器會將呼叫轉到程序鏈接表 (PLT),該表保存了一個跳轉到實際函式的蹦床。因此,直接呼叫有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/392652.html