0

I have a question that has been asked before but comes with an extra caveat. How do I properly execute a GCC inline assembly call given an x86_64 CPU, ubuntu machine, no starter files, and no standard libs? My code compiles with no warnings but does nothing on execution.

I know how to check for syscall numbers on my system, so I am certain I am calling the right number. I am trying to simply write "Hello World" to stdout using this method.

Source:


#define __NR_exit         60
#define __NR_write        1

int sys_exit(int status) {
    signed int ret;
    asm volatile
    (
        "int $0x80"
        : "=a" (ret)
        : "0"(__NR_exit), "b"(status)
        : "memory"
    );
    return ret;
}

int sys_write(int fd, const void *buf, unsigned int count) {
    signed int ret;
    asm volatile
    (
        "int $0x80\n\t"
        : "=a" (ret)
        : "0"(__NR_write), "b"(fd), "c"(buf), "d"(count)
        : "memory"
    );
    return ret;
}

void _start(void){
    sys_write(1, "Hello World\0", 11);

    sys_exit(0);
}

Comilation: gcc -nostartfiles -nodefaultlibs -nostdlib hello.c -o hello

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Jaeger
  • 11
  • 4
  • Did you say you were building a 64bit application? If so, you should be using [syscall, not int 0x80](https://stackoverflow.com/a/46087731/2189500). – David Wohlferd Jul 09 '22 at 01:23
  • Does it _silently_ abort? Run under `gdb`. Do: `b _start` then `run` Then a bunch of `si` to single step instructions – Craig Estey Jul 09 '22 at 01:38
  • Note that the ABI between functions (which reg holds arg0, etc) is somewhat different than the one used for syscalls – Craig Estey Jul 09 '22 at 01:42
  • And, your asm block may have to note which regs get changed/clobbered – Craig Estey Jul 09 '22 at 01:45
  • eax=1 / int 0x80 is `_exit` (@CraigEstey). Those are 64-bit call numbers for use with `syscall`. Use `strace` to see it, if you have a new enough kernel+strace to decode `int 0x80` system calls in a 64-bit process. See [What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?](https://stackoverflow.com/q/46087730). `#include ` to get call numbers for the mode you're in, and compile with `gcc -m32`. Don't define your own `__NR_write`. – Peter Cordes Jul 09 '22 at 03:07
  • [How to invoke a system call via syscall or sysenter in inline assembly?](https://stackoverflow.com/q/9506353) shows using `asm/unistd.h` to get call numbers. And has a 64-bit version of the wrapper function you're using. – Peter Cordes Jul 09 '22 at 03:10
  • Thank you all for taking the time to nudge me in the right direction. With a little more research, I was able to find this excellent MUSL syscall API. https://git.musl-libc.org/cgit/musl/tree/arch/x86_64/syscall_arch.h. My program works now, the and registers look good when I run it in `gdb`. – Jaeger Jul 09 '22 at 23:09

0 Answers0