简体   繁体   English

模块化编程 aarch64 汇编

[英]Modular programming aarch64 assembly

I have this simple assembly for arm architecture 64 that will print "Hello World\n" from macro I made.我有这个用于 arm 架构 64 的简单程序集,它将从我制作的宏中打印“Hello World\n”。

We know macro is analogy with function in high level programming.我们知道macro类似于高级编程中的function

So I want separate macro to another file.所以我想要单独的宏到另一个文件。 Here is my assembly code I made.这是我制作的汇编代码。

.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

To verify it, compile and run that code.要验证它,请编译并运行该代码。 Save as hello.s and run this in aarch64 devices for example android or raspi另存为hello.s并在 aarch64 设备(例如 android 或 raspi)中运行

as hello.s -o hello.o && ld hello.o -o hello && ./hello

So from above code, I made macro named print with parameter string .所以从上面的代码中,我用参数string制作了名为print的宏。 But as you see I define macro in main program.但正如你所见,我在主程序中定义了宏。 I expect I can import that print in another source file.我希望我可以将该print导入另一个源文件。 What should I do?我应该怎么办?

The counterpart to a high-level function is an assembly function.高级函数的对应物是汇编函数。 The counterpart to an assembly macro is a macro or template in a high level language.汇编宏的对应物是高级语言中的宏或模板。

Modular Programming with Functions带函数的模块化编程

The easiest way to write structured or modular code is to write functions.编写结构化或模块化代码的最简单方法是编写函数。 A function is very similar to what you wrote, but you need to return from it using a ret instruction.函数与您编写的非常相似,但您需要使用ret指令从它返回。 This print function takes the address of the string you want to print in x0 and its length in x1 .print函数获取您要在x0中打印的字符串的地址及其在x1中的长度。 It follows the AArch64 ABI and trashes registers x0 , x1 , x2 , and x8 .它遵循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

You can then call the function from any object file you like:然后,您可以从您喜欢的任何目标文件中调用该函数:

        .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

Note that as each function uses the same lr register to keep track of the return address, you may need to save the lr register to the stack in functions that call other functions.请注意,由于每个函数都使用相同的lr寄存器来跟踪返回地址,因此您可能需要将lr寄存器保存到调用其他函数的函数的堆栈中。 As registers must be pushed onto the stack in pairs on arm64, I've pushed xzr as the second register.由于必须在 arm64 上成对将寄存器推入堆栈,因此我将xzr作为第二个寄存器推入。 In practice, you'll probably want to push some other register that needs to be saved.在实践中,您可能想要推送一些需要保存的其他寄存器。

        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

Modular Programming with Macros使用宏进行模块化编程

Your macro approach is almost correct.您的宏观方法几乎是正确的。 Here is a slightly improved version.这是一个稍微改进的版本。 Note how we use \@ to generate unique labels for the strings used.请注意我们如何使用\@为使用的字符串生成唯一标签。 This allows us to not trash the numbered labels, permitting them to be used by code outside of the macro.这允许我们不丢弃编号的标签,允许宏之外的代码使用它们。

        .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

If you want to invoke macros defined in other files, you have to include these file into the other files.如果要调用其他文件中定义的宏,则必须将这些文件包含到其他文件中。 This can be done with a .include directive.这可以通过.include指令来完成。 For example, suppose you have your macros in a file named macros.inc , you can include them like this:例如,假设您将宏放在名为macros.inc的文件中,您可以像这样包含它们:

        .include "macros.inc"       // include macros

Refer to the GNU as manual for details.有关详细信息,请参阅 GNU 手册

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM