下面的代码包含一些内联汇编模板:
static inline uintptr_t arch_syscall_invoke3(uintptr_t arg1, uintptr_t arg2,
uintptr_t arg3,
uintptr_t call_id)
{
register uint32_t ret __asm__("r0") = arg1;
register uint32_t r1 __asm__("r1") = arg2;
register uint32_t r2 __asm__("r2") = arg3;
register uint32_t r6 __asm__("r6") = call_id;
__asm__ volatile("svc %[svid]\n"
: "=r"(ret), "=r"(r1), "=r"(r2) <===================== HERE 1
: [svid] "i" (_SVC_CALL_SYSTEM_CALL), <===================== HERE 2
"r" (ret), "r" (r1), "r" (r2), "r" (r6)
: "r8", "memory", "r3", "ip");
return ret;
}
我得到了最终的组装,https://godbolt.org/z/znMeEMrEz 是这样的:
push {r6, r7, r8} ------------- A -------------
sub sp, sp, #20
add r7, sp, #0
str r0, [r7, #12]
str r1, [r7, #8]
str r2, [r7, #4]
str r3, [r7]
ldr r0, [r7, #12]
ldr r1, [r7, #8]
ldr r2, [r7, #4]
ldr r6, [r7]
svc #3 ------------- B -------------
mov r3, r0 ------------- C1 -------------
mov r0, r3 ------------- C2 -------------
adds r7, r7, #20
mov sp, r7
pop {r6, r7, r8}
bx lr
从 A
到 B
,汇编代码只是确保输入参数存在于目标寄存器中。我想这是一些系统调用约定。
我不明白here 1
和here 2
的目的。
问题1:
根据这里,<code>here 1</code>应该是OutputOperands部分,这意味着
由AssemblerTemplate中的指令修改的C变量的逗号分隔列表。
这是否意味着特定请求的系统调用函数将修改ret/r0
、r1
和r2
注册表?
问题2:
对于< code>HERE 2,它表示InputOperands,也就是说:
由汇编程序模板中的指令读取的 C 表达式的逗号分隔列表。允许使用空列表。请参阅输入操作数。
根据这里,SVC
指令只期望 1 个参数 imm
。但是我们指定了 4 个输入操作数,如 ret
、r1、r2、r6
。
为什么我们需要指定这么多?
我猜svc处理程序使用这些寄存器,所以我需要在< code>SVC指令之前准备它们。但是,如果我只是像从< code>A到< code>B那样准备它们,而不把它们作为输入操作数呢?会不会有一些误差?
问题3:
最后,C1
和C2
有什么意义?它们似乎完全多余。r0
仍然存在。
我猜这是一些系统调用约定。
这是没有优化的编译结果。仔细观察代码中发生的事情,可以看到在保存r6之后,r7和r8所做的只是将r3移动到r6,其他一切都是多余的。
问题 1:这是否意味着特定请求的系统调用函数将修改 ret/r0、r1 和 r2 注册表?
没问题.
问题2:根据这里,SVC指令只需要1个参数imm。但是我们指定了4个输入操作数,如ret,r,r2,r6。
我们指定 imm 来生成正确的 SVC 指令,我们指定其余部分以确保我们调用的系统调用将在系统调用 ABI 中记录的寄存器中找到其参数。
为什么我们需要指定这么多?
根据函数名称,它是一个 3 参数的系统调用,所以我们有 3 个系统调用参数,显然还有系统调用标识符。
但是,如果我只是从 A 到 B 准备它们,而不将它们作为输入操作数提及怎么办?会不会有一些错误?
如果不在该 asm 语句中将它们作为输入提及,就无法可靠地像从 A 到 B 部分一样准备它们
。仅将函数参数分配给局部变量是不够的,因为没有任何内容可以强制此赋值和 asm 语句的正确排序。除非使用警告作为错误进行编译,并且对未使用但已设置的变量启用警告,否则不会有编译时错误。
问题3:最后,C1和C2的意义何在?它们似乎完全是多余的。r0 仍然存在。
是的。使用-O编译将消除这个冗余的动作以及大部分序言。