[Bug c/63318] Hello World C program using inline assembly to invoke write(2) on amd64 Linux fails to print Hello World
pinskia at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sat Sep 20 20:07:00 GMT 2014
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.
More information about the Gcc-bugs
mailing list