我有這個用于 arm 架構 64 的簡單程式集,它將從我制作的宏中列印“Hello World\n”。
我們知道這與高級編程中macro
的類比。function
所以我想要單獨的宏到另一個檔案。這是我制作的匯編代碼。
.data
.text
.globl _start
_start:
.macro print string
b 2f // jump to label 2 forward (so it will not bother var)
1: // label 1 (var declaration)
.asciz "\string" // store argumen (string) in memory
len_string = . - 1b // get len of string
udf #0 // if i dont use this it will branch error :(
2: // label 2 (main macro code)
mov x0, #1 // file descriptor (1 means stdout)
ldr x1, =1b // data to print (from label 1 back)
ldr x2, =len_string //len of data
mov x8, #0x40 // kernel convention 0x40 means writing
svc #0 // SuperVisorCall kernel
.endm
print "Hello " // call macro
print "World\n" //call again
_exit: // exit code return 0
mov x0,#0
mov x8,#0x5d
svc #0
要驗證它,請編譯并運行該代碼。另存為hello.s
并在 aarch64 設備中運行它,例如 android 或 raspi
as hello.s -o hello.o && ld hello.o -o hello && ./hello
print
所以從上面的代碼中,我用引數命名了宏string
。但正如你所見,我在主程式中定義了宏。我希望我可以將其匯入print
另一個源檔案。我應該怎么辦?
uj5u.com熱心網友回復:
高級函式的對應物是匯編函式。匯編宏的對應物是高級語言中的宏或模板。
帶函式的模塊化編程
撰寫結構化或模塊化代碼的最簡單方法是撰寫函式。函式與您撰寫的非常相似,但您需要使用ret
指令從它回傳。此print
函式獲取您要列印的字串的地址x0
及其長度x1
。它遵循AArch64 ABI并丟棄暫存器x0
、x1
、x2
和x8
.
.text
.type print, @function // these two directives make the function
.globl print // callable from other object files.
print: mov x2, x1 // move length into place for syscall
mov x1, x0 // move string address into place for syscall
mov x0, #1 // print to stdout
mov x8, #0x40 // do a write system call
svc #0
ret // return to caller
然后,您可以從您喜歡的任何目標檔案中呼叫該函式:
.data
hello: .ascii "hello world\n"
len= .-hello
.text
ldr x0, =hello // load string address from literal pool
mov x1, #len // load string length
bl print // call our print function
請注意,由于每個函式都使用相同的lr
暫存器來跟蹤回傳地址,因此您可能需要將lr
暫存器保存到呼叫其他函式的函式的堆疊中。由于暫存器必須在 arm64 上成對推送到堆疊中,因此我已將xzr
其作為第二個暫存器推送。在實踐中,您可能想要推送一些需要保存的其他暫存器。
str lr, xzr, [sp, #-16]! // push lr and xzr onto the stack
...
ldr x0, =hello // load string address from literal pool
mov x1, #len // load string length
bl print // call our print function
...
ldr lr, xzr, [sp], #16 // pop lr and xzr off the stack
ret
使用宏進行模塊化編程
您的宏觀方法幾乎是正確的。這是一個稍微改進的版本。請注意我們如何\@
為使用的字串生成唯一標簽。這允許我們不丟棄編號的標簽,允許宏之外的代碼使用它們。
.macro print string // define a macro print with argument string
.pushsection .data // temporarily go into .data
str\@: .ascii "\string" // define the string
len\@= .-str\@ // and its length
.popsection // go back to the previous section
mov x0, #1 // print to stdout
ldr x1, =str\@ // print our string
mov x2, #len\@ // of this length
mov x8, #0x40 // with a write system call
svc #0 // do the system call!
.endm
如果要呼叫其他檔案中定義的宏,則必須將這些檔案包含到其他檔案中。這可以通過.include
指令來完成。例如,假設您的宏在一個名為 的檔案中macros.inc
,您可以像這樣包含它們:
.include "macros.inc" // include macros
有關詳細資訊,請參閱GNU 手冊。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/486329.html