はじめに
標準Cライブラリ(Linuxではglibc)に頼らず、システムコールを呼びして見たいなとの思いから、勉強がてらアセンブラでシステムコールを呼びだす方法をまとめてみました。
アセンブラでシステムコールを呼びだす方法
まとめると、以下の通りです。
- eaxレジスタに呼び出したいシステムコールの番号を登録する。
- システムコールに指定する番号は、"/usr/include/asm/unistd.hを参照。
- asm/unistd.hから、
- 32bitコンパイル時はasm/unistd_32.hが取り込まれる。(今回はこちら)
- (参考までに)、64bit時は、asm/unistd_64.hが取り込まれる。
- asm/unistd.hから、
- システムコールに渡す引数は順番に、ebx, ecx, edxレジスタにコピーする。
- "int 0x80"で0x80割り込みを発生させることで、システムコールを発行する。
- リターンコードは、exaに格納されるので、そのレジスターをmovでコピーする。
サンプルコードです。
#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main() { pid_t pid; /* call by assembly language */ pid=0; __asm__("mov $20, %%eax;" //"$20"がgetpidのシステムコール番号 "int $0x80;" //80番で割り込みを発生させる "mov %%eax, %0;" //返り値をpid変数にコピー :"=r"(pid) ); printf("assembly: pid=%d\n",pid); /* call by glibc getpid function */ pid=0; pid=getpid(); printf("glibc : pid=%d\n",pid); return(EXIT_SUCCESS); }
実行結果です。
$ gcc -m32 -o test syscall_test.c $ ./test assembly: pid=3970 glibc : pid=3970