GCC inline assembly register naming is strange?

Programming, for all ages and all languages.
Post Reply
User avatar
AndrewAPrice
Member
Member
Posts: 2300
Joined: Mon Jun 05, 2006 11:00 pm
Location: USA (and Australia)

GCC inline assembly register naming is strange?

Post 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?
Last edited by AndrewAPrice on Wed Apr 29, 2020 1:52 pm, edited 4 times in total.
My OS is Perception.
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: GCC inline assembly register naming is strange?

Post 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.
Carpe diem!
kzinti
Member
Member
Posts: 898
Joined: Mon Feb 02, 2015 7:11 pm

Re: GCC inline assembly register naming is strange?

Post 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".
nullplan
Member
Member
Posts: 1790
Joined: Wed Aug 30, 2017 8:24 am

Re: GCC inline assembly register naming is strange?

Post 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.
Carpe diem!
User avatar
eekee
Member
Member
Posts: 891
Joined: Mon May 22, 2017 5:56 am
Location: Kerbin
Discord: eekee
Contact:

Re: GCC inline assembly register naming is strange?

Post 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.
Kaph — a modular OS intended to be easy and fun to administer and code for.
"May wisdom, fun, and the greater good shine forth in all your work." — Leo Brodie
Post Reply