作った物
カーネル/VM Advent Calendarの俺の番が回ってきた。元々用意していたネタが準備不足により使えなくなってしまったのでリアルモードでBrainfuckしてみようとなった。リアルモードBrainfuckといってもただnasmで書いただけのような気もするが、気にしないで話を進めよう。
リアルモード BrainfuckとはCPUのリアルモードで動かすBrainfuckである。今回は自作(コピペ)ブートローダから直接呼び出すようにした。構成はブートローダ、メインプログラム、Brainfuckのソースコードからなり、ブートローダとメインプログラムをバイナリにしたあと、できたバイナリとBrainfuckのソースコードをcatで繋げたものとなっている。
とりあえず解説
ブートローダはINT 0x10でディスプレイを初期化して、INT 0x10でメッセージを表示後、INT 0x13でディスクを読み込んでいる。そしてディスクをある程度読み込んだらメインプログラムへJMP。メインプログラムではBrainfuckのソースコードを読み込んで実行する。ソースコードの位置はアドレスを直接打ちこんだ。SIレジスタにBrainfuckのソースコードの位置、DIにBrainfuckで扱うメモリの位置が入っている。Brainfuckの実行に関してだが、ユーザからの入力を省いているため","が使えないのに注意。
使い方
以下のファイルがブートローダとメインプログラムになっている。nasmでバイナリにしたあと以下のようにcatで繋げる。hello.bfは自分で用意したbrainfuckのソースコードである。Hello Worldの例を下に載せておく。
cat boot bfexe hello.bf boot > brainfuck
catした後は、qemuで実行する
qemu -fda brainfuck
これで実行できるはず。以下、ファイルとHello Worldの例
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>++++++++[<++++>-]<+.[-]++++++++++.
最後にメインプログラムの部分だけ載せておく
[BITS 16] s_start: MOV AX, CS MOV DS, AX MOV SI, 0x200 CALL memset MOV DI, 0x8000 main: MOV AL, [SI] ADD SI, 1 CMP AL, '>' JE incdi CMP AL, '<' JE decdi CMP AL, '+' JE incmem CMP AL, '-' JE decmem CMP AL, '.' JE dischar CMP AL, '[' JE loopstart CMP AL, ']' JE loopend JMP bfend incdi: ADD DI, 1 JMP main decdi: SUB DI, 1 JMP main incmem: MOV AL, [DI] ADD AL, 1 MOV [DI], AL JMP main decmem: MOV AL, [DI] SUB AL, 1 MOV [DI], AL JMP main dischar: MOV AL, [DI] MOV AH, 0x0E MOV BX, 0x15 INT 0x10 JMP main loopstart: MOV AL, [DI] CMP AL, 0 JNE main MOV BP, 1 toend: OR BP, 0 JE main MOV AL, [SI] ADD SI, 1 CMP AL, '[' JE incnestfs CMP AL, ']' JE decnestfs JMP toend loopend: MOV BP, 1 SUB SI, 1 tostart: OR BP, 0 JE main SUB SI, 1 MOV AL, [SI] CMP AL, ']' JE incnestfe CMP AL, '[' JE decnestfe JMP tostart tomain: ADD SI, 1 JMP main incnestfs: ADD BP, 1 JMP toend decnestfs: SUB BP, 1 JMP toend incnestfe: ADD BP, 1 JMP tostart decnestfe: SUB BP, 1 JMP tostart memset: MOV DI, 0x8000 MOV AX, 0 MOV CX, 30000 REP STOSB RET bfend: JMP bfend TIMES 512 - ($ - $$) db 0