![](/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.