Page 1 of 1

GCC inline assembly register naming is strange?

Posted: Wed Apr 29, 2020 12:10 pm
by AndrewAPrice
As a simple example, I wanted to invoke a syscall with rdi=0 and rax=param.

My first attempt did not work:

Code: Select all

__asm__ ("syscall\n"::"rdi"(0), "rax"(param): "rcx", "r11");
Through trial and error, this eventually worked:

Code: Select all

_asm__ ("syscall\n"::"D"(0), "a"(param): "rcx", "r11");
In the GCC user manual it lists 'a', 'b', 'c', 'd', 'S', 'D' as refering to rax, rbx, rcx, rdi, rsi, rdi, But, it doesn't make it clear what to do if I wanted to use r8-r15?

I found this documentation on local register variables that suggests you could do:

Code: Select all

	register unsigned long long int syscall_num asm ("rdi") = 0;
	register unsigned long long int r_param asm ("rax") = param;

	__asm__ ("syscall\n"::"r"(syscall_num), "r"(r_param): "rcx", "r11");
Does anybody have any tips on working with inline assembly they use?

Re: GCC inline assembly register naming is strange?

Posted: Wed Apr 29, 2020 1:49 pm
by nullplan
MessiahAndrw wrote:I found [url=https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables]this documentation on local register variables[url] that suggests you could do:
Given that this is what musl does to implement syscalls on architectures with register requirements that can't be directly specified as constraints, I guess this is going to be the only way.
MessiahAndrw wrote:Does anybody have any tips on working with inline assembly they use?
Just don't. Simply implement complete functions purely in assembly. That is what I do, and if there is a performance penalty, I have not noticed it. I do not use inline assembly because it is a moving target, and getting GCC to understand precisely what will break the code and what won't is an uphill struggle. Especially since then I need to understand how GCC broke the code so I can prevent it from happening.

Re: GCC inline assembly register naming is strange?

Posted: Wed Apr 29, 2020 7:52 pm
by kzinti
MessiahAndrw wrote:Does anybody have any tips on working with inline assembly they use?
You have already found the solution. Basically you can't specify r8-r15 as constraints directly, so you do it indirectly by using local register variables. The generated output is what you would expect (i.e. it works).

Example:

Code: Select all

// Parameters to system calls
// x86_64: rax, rdi, rsi, rdx, r10, r8, r9 (we can't use rcx for arg4 because SYSCALL will clobber it)
static inline int64_t syscall6(int64_t function, int64_t arg1, int64_t arg2, int64_t arg3, int64_t arg4, int64_t arg5, int64_t arg6)
{
    int64_t result;

    register int64_t r10 asm("r10") = arg4;
    register int64_t r8 asm("r8") = arg5;
    register int64_t r9 asm("r9") = arg6;

    asm volatile (
        "syscall"
        : "=a"(result)
        : "a"(function),
          "D"(arg1),
          "S"(arg2),
          "d"(arg3),
          "r"(r10),
          "r"(r8),
          "r"(r9)
        : "memory"
    );

    return result;
}
nullplan wrote:I do not use inline assembly because it is a moving target (...)
Oh come on now... :) I agree with you that it is difficult, error prone and probably not worth it for most usage / people. The performance improvement argument is also dubious. But it is not a "moving target".

Re: GCC inline assembly register naming is strange?

Posted: Thu Apr 30, 2020 4:00 am
by nullplan
kzinti wrote:Oh come on now... :) I agree with you that it is difficult, error prone and probably not worth it for most usage / people. The performance improvement argument is also dubious. But it is not a "moving target".
It is if you didn't get the constraints/clobbers right. And you don't notice they are wrong until an optimizer breaks things for you, and maybe that optimizer is only in next version's GCC.

Re: GCC inline assembly register naming is strange?

Posted: Sat May 02, 2020 10:37 am
by eekee
FWIW, Ken Thompson never even bothered implementing inline assembly in the compilers he wrote in the 90s. Some smart people have worked on those compilers since, and none have seen fit to add it.