自分も、そんなコンパイラを作ってみたいと思いました。
そこで、まずはアセンブリ言語ではないソースコードをアセンブリ言語のソースコードに変換するプログラムを作りました。
#include
#define STACK_LIMIT 1024
void printStandardLibrary(void) {
puts(".code16gcc");
puts("_start:");
puts("\tmovw $0x1000,%cx");
puts("\tmovw %cx,%ds");
puts("\txorw %cx,%cx");
puts("\txorw %bx,%bx");
puts("_arrayinit_loop:");
puts("\tmovb $0,%ds:(%bx)");
puts("\tincw %bx");
puts("\tloopw _arrayinit_loop");
puts("\txorw %si,%si");
puts("\tjmp _main");
puts("_input_char:");
puts("\txorw %ax,%ax");
puts("\tint $0x16");
puts("\ttestb %al,%al");
puts("\tjz _input_char");
puts("\tmovb %al,%ds:(%si)");
puts("\tretw");
puts("_output_char:");
puts("\tmovb $0x0E,%ah");
puts("\tmovb %ds:(%si),%al");
puts("\tmovw $0x0007,%bx");
puts("\tint $0x10");
puts("\tretw");
puts("_main:");
}
int main(void) {
int input=0;
int bracketCount=0;
int stack[STACK_LIMIT]={};
int stackNum=0;
printStandardLibrary();
while((input=getchar())!=EOF) {
switch(input) {
case '>':
puts("\tincw %si");
break;
case '=STACK_LIMIT) {
fputs("error: internal stack overflow (too many \"[\")\n",stderr);
return 1;
}
stack[stackNum++]=bracketCount;
bracketCount++;
break;
case ']':
if(stackNum0) {
fputs("error: \"[\" without \"]\" exists\n",stderr);
return 1;
}
puts("_hlt_loop:");
puts("\thlt");
puts("\tjmp _hlt_loop");
return 0;
}
標準入力からBrainfu*kのソースコードを入れると、標準出力からアセンブリ言語のプログラムが出てきます。
試しに変換してみましょう。
Wikipediaより、Hello worldプログラム (このプログラムはクリエイティブ・コモンズ 表示-継承 3.0 Unportedライセンスの下で利用可能です)
このプログラムでアセンブリ言語に変換すると、こうなりました。
► スポイラーを表示
B900108ED931C931DBC6070043E2FA31F6EB1531C0CD1684C074F88804C3B40E
8A04BB0700CD10C3800401800401800401800401800401800401800401800401
8004018A0484C074574680040180040180040180040180040180040180040180
0401468004018004018004018004018004018004018004018004018004018004
01800401468004018004018004018004018004014E4E4E802C018A0484C075A9
46E87AFF46800401800401E870FF800401800401800401800401800401800401
800401E858FFE855FF800401800401800401E849FF46802C01E842FF802C0180
2C01802C01802C01802C01802C01802C01802C01802C01802C01802C01802C01
E81BFF4E800401800401800401800401800401800401800401800401E8FFFE80
2C01802C01802C01802C01802C01802C01802C01802C01E8E4FE800401800401
800401E8D8FE802C01802C01802C01802C01802C01802C01E8C3FE802C01802C
01802C01802C01802C01802C01802C01802C01E8A8FE46800401E8A1FEF4EBFD
そこで、対症療法として1行目の"E2FA"を"9090"に書き換え、最後の行の"F4"を"90"に書き換えます。
そして書き換えた文字列をx86 WebStudioの入力欄にコピペし、
「ディスプレイ」ボタンで黒い画面を出してから「実行」ボタンを押すと、
きちんと"Hello, world!"と表示されることがわかります。
これでアセンブリ言語ではないソースコードをアセンブリ言語に変換できることがわかったので、
あとはこのプログラムを少し改造し、gccが出力している機械語を真似て直接出力するようにすれば、
「コンパイラ」の完成!となると思います。