続・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に指定できていなくてハマった・・・