続・libc なんていらないもん!

たけおかさんにwrite()くらいしてほしいと突っ込みをいただいたので、やってみました。

Linux 32bit

int
write(int filedes, const void *buf, unsigned int nbyte)
{
    int rv;

    asm("movl   $4,%%eax\n\t"
        "movl	%3,%%edx\n\t"
        "movl	%2,%%ecx\n\t"
        "movl	%1,%%ebx\n\t"
	"int	$0x80\n\t"
        "movl   %%eax,%0"
        :"=r"(rv)
        :"r"(filedes),"r"(buf),"r"(nbyte)
        :"%eax","%edx","%esp");

    return(rv);
}

void
_exit(int status)
{
    int tmp;

    asm("movl	$1,%%eax\n\t"
	"movl   %1,%%ebx\n\t"
        "int	$0x80"
        :"=r"(tmp)
        :"r"(status)
        :"%eax","%ebx");
}

int
main(int argc, char *argv[])
{
    int rv;

    rv = write(2, "hello, world\n", 13);

    return(rv);
}

void
_start(int args)
{
    int rv;

    rv = main(0, 0);

    _exit(rv);
}


% gcc -S write_nocrt_linux.c && gcc -c write_nocrt_linux.s && ld -nostdlib write_nocrt_linux.o
write_nocrt_linux.c: In function ‘_exit’:
write_nocrt_linux.c:30: 警告: ‘noreturn’ function does return
% ./a.out
hello, world
% echo $?
13

Mac OS X 64bit

int
write(int filedes, const void *buf, unsigned int nbyte)
{
    int rv;

    asm("mov	$0x2000004,%%rax\n\t"
	"mov	%1,%%rbx\n\t"
	"mov	(%2),%%rcx\n\t"
	"mov	%3,%%edx\n\t"
	"syscall\n\t"
	"mov	%%eax,%0"	
        :"=r"(rv)
        :"g"(filedes),"r"(buf),"r"(nbyte)
        :"%rax","%rbx","%rcx");

    return(rv);
}

void
_exit(int status)
{
    int tmp;

    asm("mov    $0x2000001,%%rax\n\t"
        "mov    %1,%%rdi\n\t"
        "syscall"
        :"=r"(tmp)
	:"g"(status)
	:"%rax","%rdi");
}

int
main(int argc, char *argv[])
{
    int rv;

    rv = write(2, "hello, world\n", 13);

    return(rv);
}

void
_start(int args)
{
    int rv;

    rv = main(0, 0);

    _exit(rv);
}


% gcc -S write_nocrt_lion.c && gcc -c write_nocrt_lion.s && gcc -nostdlib -e __start write_nocrt_lion.o
write_nocrt_lion.c: In function ‘_exit’:
write_nocrt_lion.c:30: warning: ‘noreturn’ function does return
ld: warning: symbol dyld_stub_binder not found, normally in libSystem.dylib
% ./a.out
hello, world
% echo $?
13

Mac OS X 32bit

int
write(int filedes, const void *buf, unsigned int nbyte)
{
    int rv;

    asm("movl	$4,%%eax\n\t"
	"pushl	%3\n\t"
	"pushl	%2\n\t"
	"pushl	%1\n\t"
	"leal	-0x4(%%esp),%%ecx\n\t"
	"movl	$ret_addr,%%edx\n\t"
	"sysenter\n\t"
	"ret_addr:\n\t"
	"addl	$12,%%esp\n\t"
	"movl	%%eax,%0\n\t"
        :"=r"(rv)
        :"r"(filedes),"r"(buf),"r"(nbyte)
        :"%eax","%edx","%esp");

    return(rv);
}

void
_exit(int status)
{
    int tmp;

    asm("movl   $1,%%eax\n\t"
        "pushl  %1\n\t"
	"leal -0x4(%%esp),%%ecx\n\t"
        "sysenter\n\t"
        :"=r"(tmp)
	:"r"(status)
	:"%eax");
}

int
main(int argc, char *argv[])
{
    int rv;

    rv = write(2, "hello, world\n", 13);

    return(rv);
}

void
_start(int args)
{
    int rv;

    rv = main(0, 0);

    _exit(rv);
}


% gcc -g -S write_nocrt_sl.c && gcc -c write_nocrt_sl.s && ld -e __start write_nocrt_sl.o
write_nocrt_sl.c: In function ‘_exit’:
write_nocrt_sl.c:35: warning: ‘noreturn’ function does return
% ./a.out
hello, world
% echo $?
13

ふぅ、sysenterの戻り値をきちんとEDXに指定できていなくてハマった・・・