![](/img/trans.png)
[英]Show what's current value of registers. (AArch64 Android assembly debugging)
[英]Modular programming aarch64 assembly
我有這個用於 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
所以從上面的代碼中,我用參數string
制作了名為print
的宏。 但正如你所見,我在主程序中定義了宏。 我希望我可以將該print
導入另一個源文件。 我應該怎么辦?
高級函數的對應物是匯編函數。 匯編宏的對應物是高級語言中的宏或模板。
編寫結構化或模塊化代碼的最簡單方法是編寫函數。 函數與您編寫的非常相似,但您需要使用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 手冊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.