FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

「30日でできる!OS自作入門」を読み始めた (20日目. APIの実装)

30日でできる! OS自作入門

30日でできる! OS自作入門

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;
}

これで、アプリケーションを呼び出せるようにした。

f:id:msyksphinz:20180421143543p:plain
図. APIを使って、文字列を出力する。