R10 register limitation in gcc inline x86_64 assembly

I am going to write a very lightweight libc replacement library so that I can better understand the kernel - application interface. The first task is to get some wrappers of system calls. I have successfully received 1 to 3 argument handlers, but I am struggling with 4 var arguments. Here is my starting point:

long _syscall4(long type, long a1, long a2, long a3, long a4) { long ret; asm ( "syscall" : "=a"(ret) : "a"(type), "D"(a1), "S"(a2), "d"(a3), "r10"(a4) : "c", "r11" ); return ret; } 

The compiler gives me the following error:

 error: matching constraint references invalid operand number 

My _syscall3 function works fine, but does not use r10 or has a clobber list.

Any thoughts?

+9
source share
2 answers

There are no restrictions for registers: %r8 .. %15 . However, later ones (as in gcc-4.x) should accept:

 register long r10 asm("r10") = a4; 

then use the input constraint: "r" (r10) for your asm statement.
https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html


Note that forcing the selection of the "r" constraint for Extended asm is the only behavior that GCC guarantees for asm registers. Things like register void *rsp asm("rsp"); and void *stack_pointer = rsp; sometimes I work, but it is not guaranteed and is no longer recommended.


You will want your asm shell operator syscall to be volatile and have a "memory" clobber, unless you write special shells for specific system calls to know which arguments are pointers using dummy input or memory output (as per instruction As I point out that the memory pointed to by * the built-in argument of ASM can be used? )

This is necessary for volatile because the execution of write(1, buf, 16) should print a buffer twice, not just the CSE return value! System calls are usually not pure functions of their inputs, so you need volatile .

(Some special system call shells, such as getpid can be non-volatile, because they return the same thing each time, unless you use fork. But getpid more efficient if executed through VDSO, so it does not need to enter the getpid kernel first, if you are working on Linux, then if you make a special shell for getpid and clock_gettime you probably do not need syscall in the first place. See syscall Linux syscall system syscall )

Clobber "memory" necessary because a pointer in a register does not mean that the specified memory is also an input or output. Buffer storages that are read only by the write system call should not be optimized as dead storages. Or for munmap , it is better for the compiler to complete any load / save before the memory is mapped. Some system calls do not accept any pointers and do not need a "memory" , but a universal shell should make the worst case assumptions.

register... asm("r10") usually does not require asm volatile or "memory" clobbers, and the syscall shell does.

+7
source

Presumably, since no instructions have a specific requirement for the r10 register, gcc people did not create restrictions for it (given that the restrictions mainly relate to machine descriptions). If you insist on inline asm, I don't think you can do better than use the general "r" (or "m" ) r10 and move to r10 yourself (and add it to the clobber list).

0
source

All Articles