https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63318

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #5 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
This is still invalid.
Even though this is not fully correct:
#include <unistd.h>

int main(void)
{
    const char hello[] = "Hello World!\n";
    const size_t hello_size = sizeof(hello);
    ssize_t ret;
    asm volatile
    (
        "movl $1, %%eax\n\t"
        "movl $1, %%edi\n\t"
        "movq %1, %%rsi\n\t"
        "movl %2, %%edx\n\t"
        "syscall"
        : "=&a"(ret)
        : "g"(hello), "g"(hello_size)
        : "%rdi", "%rsi", "%rdx", "%rcx", "%r11"
    );
    return 0;
}

It works as you mark operand one as being clobbered early (which is kinda
correct as you change eax the very first instruction.

Really the correct way is to do:
#include <unistd.h>

static inline syscall_1(long long syscallnum, long long arg0, long long arg1,
long long arg2)
{
  register long long syscallnum_ __asm__("eax");
  register long long arg0_ __asm__("edi");
  register long long arg1_ __asm__("rsi");
  register long long arg2_ __asm__("edx");
  syscallnum_ = syscallnum;
  arg0_ = arg0;
  arg1_ = arg1;
  arg2_ = arg2;
  asm volatile
    (
        "syscall"
        : "+r"(syscallnum_)
        : "r"(arg0_), "r"(arg1_), "r"(arg2_)
        : "%rcx", "%r11", "memory"
    );
  return syscallnum_;
}


int main(void)
{
    const char hello[] = "Hello World!\n";
    const size_t hello_size = sizeof(hello);
    ssize_t ret;
    ret = syscall_1(/*write*/1, /*fileno*/1,  hello, hello_size);
    return 0;
}

Note I might have swapped syscallnum and arg0.

Reply via email to