The HyperNews Linux KHG Discussion Pages

Note: would be nice to explain syscall macros

Forum: How System Calls Work on Linux/i86
Keywords: sycall
Date: Fri, 13 Sep 1996 01:37:11 GMT
From: Tim Bird <>

The syscall macros are a little dense to decipher. It took me a while to determine how the macro syscall1(int,setuid,uid_t,uid) expanded into the assembly code shown.

It might be nice to show the macro, and explain a little about how it gets expanded.

Here is the source for the _syscall1 macro

   #define _syscall1(type,name,type1,arg1) \
        type name(type1 arg1) \
        { \
        long __res; \
        __asm__ volatile ("int $0x80" \
                : "=a" (__res) \
                : "0" (__NR_##name),"b" ((long)(arg1))); \
        if (__res >= 0) \
                return (type) __res; \
        errno = -__res; \
        return -1; \
        }

When expanded, this become the code
        int setuid(uid_t uid)
        {
                long __res;
                __asm__ volatile ("int $0x80" \
                        : "=a" (__res) \
                        : "0" (__NR_setuid), "b" ((long)(uid)));
                if (__res >= 0 )
                        return (int) __res;
                errno = -__res;
                return -1;
        }

It's pretty easy to see how the cleanup code converts
into assembly, but the setup code eluded me until
I figured out the following:
        "=a" (__res) means the result comes back in %eax
        "0" (__NR_setuid) means put the system call number
                into %eax on entry
        "b" ((long)(uid) means put the first argument
                into %ebx on entry

syscallX macros that use additional parameters use %ecx, %edx, %esi, and %edi to hold additional values passed through the call.