I'm having a go at writing a very light weight libc replacement library so that I can better understand the kernel - application interface. The first task is clearly getting some system call wrappers in place. I've successfully got 1 to 3 argument wrappers working but I'm struggling with a 4 argument varient. Here's my starting point:
long _syscall4(long type, long a1, long a2, long a3, long a4)
{
long ret;
asm
(
"syscall"
: "=a"(ret) // return value
: "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4)
: "c", "r11", "memory" // some syscalls read or write memory
// the syscall insn instruction itself destroys RCX and R11
);
return ret;
}
(Editor's note: this is safe and usable, and a good example, after applying answer's way to handle r10. MUSL libc has some similar macros.)
The compiler gives me the following error:
error: matching constraint references invalid operand number
My _syscall3 function works fine but doesn't use r10 or have a clobber list.
(Editor's note: it wouldn't be safe to have no clobber list: you need to tell the compiler that RCX and R11 are overwritten, and that "memory" should be in sync before the system call which may read or write memory. If you wanted to write specific wrappers for specific system calls, you could selectively omit "memory" clobbers, or use dummy memory operands based on which parameters are pointers for that system call.
If this _syscall4 function can't inline, the register and "memory" clobbers won't in practice cause any problem, but you should make these able to inline; inlining this system call will take less code at the call site than calling a non-inline wrapper function.)