0

I have this function:

#include <cstdint>

using ::std::intptr_t;

struct syscall_param {
   syscall_param(intptr_t v) : value(v) { }
   syscall_param(void *v) : value(reinterpret_cast<::std::intptr_t>(v)) { }
   intptr_t value;
};

inline intptr_t do_syscall(syscall_param const &callnum,
                           syscall_param const &p1,
                           syscall_param const &p2,
                           syscall_param const &p3,
                           syscall_param const &p4,
                           syscall_param const &p5,
                           syscall_param const &p6)
{
   intptr_t retval;
   asm volatile (
      "movq %5, %%r10\n\t"
      "movq %6, %%r8\n\t"
      "movq %7, %%r9\n\t"
      "syscall\n\t"
       :"=a"(retval)
       :"a"(callnum.value), "D"(p1.value), "S"(p2.value), "d"(p3.value), "g"(p4.value), "g"(p5.value), "g"(p6.value)
       :"%rcx", "%r11", "%r10", "%r8", "%r9"
      );
   return retval;
}

I would really like to get rid of the movq instructions by using contraints. While I can use constraints to get things into the rax, edi, esi, and rdx registers, there don't seem to be any constraints that let me get things into the r10, r8, and r9 registers. It seems like there ought to be a constrain that would allow me to get things into an arbitrary r# register. Am I missing something? Is there a better way to do what I want?

Omnifarious
  • 54,333
  • 19
  • 131
  • 194
  • 1
    Yes you can use [Local Register Variables](https://gcc.gnu.org/onlinedocs/gcc-6.3.0/gcc/Local-Register-Variables.html) – Michael Petch Jun 26 '20 at 22:57
  • 1
    You will also want to use a `memory` clobber because it appears you could be passing addresses through registers rather than memory constraints. – Michael Petch Jun 26 '20 at 23:02
  • @MichaelPetch - Local register variables do not appear to have the desired effect. https://godbolt.org/z/SzQZnS - Also, what's a memory clobber? – Omnifarious Jun 26 '20 at 23:21
  • @MichaelPetch - I think I figured out how to make the local register variables work for me: https://godbolt.org/z/saNrAo - that just leaves the memory clobber. – Omnifarious Jun 26 '20 at 23:29
  • 1
    2 of the the linked duplicates show correct syscall wrappers with `"memory"` in the clobber list, e.g. [How to specify register constraints on the Intel x86\_64 register r8 to r15 in GCC inline assembly?](https://stackoverflow.com/a/31774784). Docs for "memory" clobber: https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html. See also [How can I indicate that the memory \*pointed\* to by an inline ASM argument may be used?](https://stackoverflow.com/q/56432259) for why this is a problem. – Peter Cordes Jun 26 '20 at 23:38
  • @PeterCordes - Thanks! I got it. I maybe should've searched harder for those answers, but I didn't find them on a first googling. – Omnifarious Jun 26 '20 at 23:40

0 Answers0