c - Aarch64 程序集中的系统调用调用

标签 c linux assembly system-calls arm64

我正在为 Aarch64 arm bit cpu 开发一个系统调用处理函数,我正在研究它是如何在 x86 汇编中完成的,但我无法弄清楚它是如何在 Aarch64 汇编中完成的。

我在 github 上看这个例子:https://github.com/rockytriton/LLD/blob/main/linux_os/part1/src/start.S这是用 x86 汇编语言编写的。

.globl _syscall
_syscall:
    movq %rdi, %rax
    movq %rsi, %rdi
    movq %rdx, %rsi
    movq %rcx, %rdx
    movq %r8, %r10
    movq %r9, %r8
    movq 8(%rsp), %r9
    syscall
    ret

还有一些在线等价物,如本 answer 所示不满足相同的函数调用设计。这是用 Aarch64 程序集编写的。

/* Generated by gensyscalls.py. Do not edit. */

#include <private/bionic_asm.h>

    .hidden __set_errno

ENTRY(write)
    mov     x8, __NR_write
    svc     #0

    cmn     x0, #(MAX_ERRNO + 1)
    cneg    x0, x0, hi
    b.hi    __set_errno

    ret
END(write)

到目前为止,我有这段代码(从 x86 移植到 Aarch64 的效果很差):

.globl _syscall
_syscall:
    mov     x8, r7
    svc     #0
    cmn     x0, #(4095 + 1)
    cneg    x0, x0, hi
    ret

它确实不起作用,但我还是试过了,具有讽刺意味的是,当我组装它时,它似乎不喜欢 r7 的寄存器名称,我不太明白为什么,因为它应该是函数调用的参数(见下文)。

我的 C 程序的头文件中有一个函数布局,如下所示:unsigned long _syscall(int num, void *a0, void *a1, void *a2, void *a3, void *a4, void *a5) , 有没有人对如何在 Aarch64 程序集中重新创建相同的系统调用处理程序功能有任何想法 - 我在移植方面的尝试没有成功。我对此很迷茫,因为汇编不是我的强项 - 具有讽刺意味的是,这是我项目中唯一需要的汇编。

非常感谢!

最佳答案

如另一个答案所示,当您使用 svc 发出系统调用时,您应该在 x8 中有系统调用号,在 中有参数x0-x5.

然而,根据ARM ABI ,参数从左到右传递给寄存器 x0-x7 中的 C 函数。 (文档使用 r0-r7 混淆;根据它们是 64 位值还是 32 位值,这意味着 x0-x7w0-w7。 AArch64 没有名为 r7 或类似名称的寄存器,但 ARM32 有。)

因此系统调用号在 w0 中,而它应该在 x8 中(或等同于 w8,因为它总是正数32位数字);第一个参数 a0 在需要在 x0 中时在 x1 中;等等。因此,您需要一些代码来随机播放它们。

    mov w8, w0
    mov x0, x1
    mov x1, x2
    mov x2, x3
    mov x3, x4
    mov x4, x5
    mov x5, x6
    svc #0

(如果你把 num 参数放在参数列表的末尾而不是开头,你可以省去一些麻烦,如果你不想改变现有的,也许可以借助宏代码。那么你只需要 mov w8, w6 ; svc#0。)

在另一端,svc#0x0 中留下一个返回值。但是,如果系统调用失败,则 x0 不包含 -1 而是应返回的 errno 代码的负值(在 -1 和 -4095 之间(含)。此测试与检查作为无符号值的返回值是否高于 -4096 相同。当发生这种情况时,通常您希望将 errno 设置为 -x0,然后将 x0 设置为 -1(以便系统调用函数返回 -1

不清楚您希望 syscall 函数在出现错误时如何运行。按照您的代码,它将否定负错误代码,然后通过将其保留在 x0 中返回它,这可能不是您想要的。例如,如果您尝试使用 syscall 打开文件,但由于文件不存在而失败并返回 ENOENT,则 x0 从系统调用返回时将包含 -2。您的测试将否定它并且您的 syscall 函数将返回 2,这与 open 成功并在 fd 2 上打开文件没有区别。您可能想提出一些其他机制,但我不知道你是否想要一个全局变量,如 errno 或其他东西。

关于c - Aarch64 程序集中的系统调用调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68711164/

相关文章:

c - 宏 foo(a,b, ;) 的含义

linux - Expect:如何遍历目录中的文件?

c - ARM 汇编器返回指针

assembly - 如何将字符串的第一个字符与 x86-64 汇编中的另一个字符进行比较?

服务器应用程序中的 C 内存管理

c - malloc 是否需要操作系统支持?

linux - 在 Bash 中获取前一天的 'yyyymmdd' 格式

c++ - 为什么树向量化会使这种排序算法慢2倍?

c - fatal error : interrupt. h : No such file or directory #include <interrupt. h>

linux zip 命令不包含父文件夹