みけCATのにっき(仮)
つれづれなるまゝに、日くらし、PCにむかひて、心に移りゆくよしなし事を、そこはかとなく書きつくれば、あやしうこそものぐるほしけれ。
(本当か!?)
出典

コンパイラを作りたい ACT.2

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

コンパイラを作りたい ACT.2

投稿記事 by みけCAT » 11年前

前の日記でBrainfu*kのソースコードをアセンブリ言語に変換するプログラムを紹介しましたが、
あまりにもそのまますぎたので、今回は「適化」を導入してみました。
「最適化」と言えるほどの高度な処理はしていないので「適化」です。

CODE:

#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 isTekikaTaisyou(int c) {
	return c=='' || c=='+' || c=='-';
}

int main(void) {
	int input=0;
	int bracketCount=0;
	int stack[STACK_LIMIT]={};
	int stackNum=0;
	int prevChar='\0';
	int charCount=1;
	printStandardLibrary();
	for(;;) {
		input=getchar();
		if(input==prevChar && isTekikaTaisyou(input)) {
			charCount++;
		} else {
			switch(prevChar) {
				case '>':
					if(charCount==1)puts("\tincw %si");
					else if(charCount>0)printf("\taddw $%d,%%si\n",charCount);
					break;
				case '0)printf("\tsubw $%d,%%si\n",charCount);
					break;
				case '+':
					charCount%=256;
					if(charCount==1)puts("\tincb %ds:(%si)");
					else if(charCount>0)printf("\taddb $%d,%%ds:(%%si)\n",charCount);
					break;
				case '-':
					charCount%=256;
					if(charCount==1)puts("\tdecb %ds:(%si)");
					else if(charCount>0)printf("\tsubb $%d,%%ds:(%%si)\n",charCount);
					break;
				case '.':
					puts("\tcallw _output_char");
					break;
				case ',':
					puts("\tcallw _input_char");
					break;
				case '[':
					puts("\tmovb %ds:(%si),%al");
					puts("\ttestb %al,%al");
					printf("\tjz _bracket%d_e\n",bracketCount);
					printf("_bracket%d_s:\n",bracketCount);
					if(stackNum>=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;
}
前回のソースコードとの違いは、同じ加減算処理を1個の命令にまとめる「適化」処理を行うようにしたことです。

今回は、このFizzBuzzのソースコードを変換してみます。

CODE:

>>>++++[-]>-]>>>>>++++[-]>>-]
>>++++++++++
>>++++++[-]
>>>>>++++[-]>-]
++++++++++>+++>+++++
>+>>+>-[
	[->+>---------->>>>>+>>>->->++>>+>+>->>-[>>>>[>->>>-]
	>>>>>>>>>[->.>>..>>>>>>>>>>>>]
	>[->.>..>>>>>>>>>>>>>]
	>+>>>->>>[-]]]>>>>>>>]
	-]
変換結果
► スポイラーを表示
前回のプログラムの出力は機械語換算で1244バイトでしたが、今回のプログラムでは748バイトになりました。
それでも512バイトを超えているので、x86 WebStudioでは残念ながら実行できないようです。

さて、次こそはコンパイラの制作ですかね。

コメントはまだありません。