Below code contains some inline assembly template:
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;
}
And I got the final assembly with https://godbolt.org/z/znMeEMrEz like this:
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
From A
to B
, the assembly code just ensure the input arguments are present in the targeted registers. I guess this is some system call convention.
I don't understand the purpose of HERE 1
and HERE 2
.
Question 1:
According to here, HERE 1
should be the OutputOperands part, which means
A comma-separated list of the C variables modified by the instructions in the AssemblerTemplate.
Does this mean the specific requested system call function will modify the ret/r0
, r1
and r2
regitser?
Question 2:
For HERE 2
, it means InputOperands, which means:
A comma-separated list of C expressions read by the instructions in the AssemblerTemplate. An empty list is permitted. See InputOperands.
According to here, the SVC
instruction expects only 1 argument imm
.
But we specify 4 input operands like ret
, r1
, r2
, r6
.
Why do we need to specify so many of them?
I guess these registers are used by svc handler so I need to prepare them before the SVC
instruction. But what if I just prepare them like from A
to B
and do not mention them as the input operands? Will there be some error?
Question 3:
And at last, what's the point of the C1
and C2
? They seem totally redundant. The r0
is still there.