簡體   English   中英

模塊化編程 aarch64 匯編

[英]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並丟棄寄存器x0x1x2x8

        .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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM