- 作者: 川合秀実
- 出版社/メーカー: 毎日コミュニケーションズ
- 発売日: 2006/03/01
- メディア: 単行本
- 購入: 36人 クリック: 735回
- この商品を含むブログ (299件) を見る
30日でできる!20日目はOSのAPIを実装する。まずはコンソールに文字を表示するAPIを実装している。 最初はレジスタアドレスを決め打ちしてcons_putcharを呼び出していたのだけれども、これは良くないので割り込みを使ってAPIを呼び出すようにしている。
最初のcons_putcharをアドレスを固定して呼び出す方法は、どうも方式が違っていて本書とアドレスが異なっているので最初は苦労した。 以下の記事を参考にしてアドレスを特定するようにした。
OS自作入門20日目 【Linux】 | APIを作る | サラリーマンがハッカーを真剣に目指す
なるほど、バイナリファイルをダンプしてアドレスを見つけるのか。
$(TARGET).bin: $(OBJ_FILES) ld -Map bootpack.map -m elf_i386 -e HariMain -n -Thrb.ld -static -o $(TARGET).bin $^ hexdump -C $(TARGET).bin > $(TARGET).bin.dmp
上記を実行すると、bootpack.mapの中にアドレスが記述されている。
... .text 0x0000000000006300 0x2808 console.o 0x0000000000006590 cons_newline 0x0000000000006680 cmd_mem 0x00000000000069a0 cmd_cls 0x0000000000006a10 cmd_dir 0x0000000000006e50 cmd_type 0x00000000000072a0 cmd_hlt 0x0000000000007500 cons_putchar
そこで、関数の呼び出し位置を決める。
[BITS 32] mov al, 'h' call 2*8:0x7500 mov al, 'e' call 2*8:0x7500 mov al, 'l'
次に、この方式はアドレスが変わるたびに場所を書き換えないといけないので、割り込みを使ってAPIを呼び出すように変更している。 さらに、1種類の割り込みを呼び出せば、それからAPIの種類を判断してジャンプできるようにした。
void hrb_api (int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax) { struct CONSOLE *cons = (struct CONSOLE *) *((int *)0xfec); if (edx == 1) { cons_putchar (cons, eax & 0xff, 1); } else if (edx == 2) { cons_putstr0 (cons, (char *) ebx); } else if (edx == 3) { cons_putstr1 (cons, (char *) ebx, ecx); } return; }
これで、アプリケーションを呼び出せるようにした。
図. APIを使って、文字列を出力する。