[英]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.
汇编宏的对应物是高级语言中的宏或模板。
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并丢弃寄存器
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
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
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.