コンパイラ実装会(3)に参加してきた。その3
前回に引き続き、今回は、brainfuckのコード から アセンブラのコード を生成して出力する node.jsのコードを作成しました。
想定している環境は、Linuxのx86_64です。
ネット上のアセンブラの情報がNASMとGASとIntel記法とAT&T記法でごちゃってて、ちょっと一苦労。。。
アセンブラにもNASMとGAS等があり、今回は、GASを。
記法はIntel記法とAT&T記法がありますが、Intel記法です。
bf2asm.js
var fs = require('fs'); var cmds = ""; var indent = 0; var code = fs.readFileSync('data','utf-8'); var trans = function(code) { var arr = code.split(''); while(arr.length != 0){ var c = arr.shift(); switch (c) { case '+' : cmds += 'inc byte ptr[esi]\n'; break; case '-' : cmds += 'dec byte ptr[esi]\n'; break; case '>' : cmds += 'inc esi\n'; break; case '<' : cmds += 'dec esi\n'; break; case '.' : cmds += 'mov edx, 0x1\n'; cmds += 'mov ecx, esi\n'; cmds += 'mov ebx, 0x1\n'; cmds += 'mov eax, 0x4\n'; cmds += 'int 0x80\n'; break; //case ',' : //cmds += 'ptr = getchar();\n'; //break; case '[' : cmds += indent*2 + ':\n'; cmds += 'cmp byte ptr [esi],0\n'; cmds += 'jz ' + (indent*2+1) + 'f\n'; indent += 1; break; case ']' : indent -= 1; cmds += 'jmp ' + indent*2 + "b\n"; cmds += (indent*2+1) + ':\n'; break; default: } } return cmds; } var out = ''; out += '.intel_syntax noprefix\n'; out += '.comm mem, 30000\n'; out += '.code64\n'; out += '.globl _start\n'; out += '_start:\n'; out += 'lea esi, mem\n'; out += trans(code); out += 'xor ebx,ebx\n'; out += 'mov eax,0x1\n'; out += 'int 0x80\n'; fs.writeFileSync('./bf.s',out,'utf-8');
data (brainfuckのHelloコード)
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++ ++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]> ++++++++[<++++>-]<+.[-]++++++++++.
実行方法
$ node bf2asm.js $ as bf.s -o bf.o $ ld bf.o $ ./a.out Hello World!