upvote
Yes, something like this:

  static inline long read(int fd, void *buf, long count) {
    register long rax asm("rax") = __NR_read;
    register long rdi asm("rdi") = (long)fd;
    register long rsi asm("rsi") = (long)buf;
    register long rdx asm("rdx") = count;

    asm volatile(
        "syscall"
        : "+r"(rax)
        : "r"(rdi), "r"(rsi), "r"(rdx)
        : "rcx", "r11", "memory"
    );
    return rax;
  }
reply
The linux kernel also has its own headers (IIRC it was something like <asm/unistd.h> and/or <sys/syscall.h>, but might depend on architecture and version) where it will provide the stub asm statements.

In my memory the syscall ABI has changed a few times (i386 had int $0x80, then sysenter, then abstracting it in the vdso, then amd64 has 'syscall'), so it may be easier to let the kernel header provide the mechanism.

reply
The Linux syscall ABI is (famously) stable; on x86* you can still call into 0x80 just fine. There might be new interfaces made available, but existing programs shouldn't break. Although, in C there could be value in abstracting over the per-platform differences like int/syscall. I've only ever done raw syscalls from assembly where portability was rather moot:)
reply
It's quite easy to get it to do syscalls directly, I even got Fable to do a simple standalone TLS implementation (in C). Not really useful since it hardcoded a set of supported algorithms etc., but it's fun to see how "simple" you can force it to go.
reply