脳死で作る!クソ低機能アセンブラ
ネットコンテンツへようこそ これやります
そのうち「脳死で作る!クソ低機能アセンブラ」ってタイトルで記事書きます
— 可愛姫【公式】 (@Cra2yPierr0t) April 18, 2019
アセンブラ is 何
アセンブリをバイナリに変換するやつです、出たバイナリをCPUが食べて(人類が)幸せになります。
何相手のアセンブラ作るの?
そう、これが問題。 CPUが違えばアセンブリも違う、怖い、言オリかよ。
詳しくは以下の素晴らしい本が出てるので買いましょう、買いましょう
- 作者: 坂井弘亮
- 出版社/メーカー: 秀和システム
- 発売日: 2017/09/15
- メディア: 単行本
- この商品を含むブログ (2件) を見る
だから何相手のアセンブラ作るの??
コンピュータシステムの理論と実装という本がある。(通称 nand2tetris)
Nandゲートから各種ゲート、そっからALU、なんやかんやあってCPU、OS作ってテトリス動かそうぜ!
そんな本です。 エモいですね?楽しそうですね? 買いましょう作りましょう、そんで教えて下さい。
コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方
- 作者: Noam Nisan,Shimon Schocken,斎藤康毅
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/03/25
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
で?
そう、それでですね、このnand2tetrisは、著者の作ったハードウェアシミュレータ上で自分で書いたHDLを動かして進めてくのが基本的な序盤のスタイルなんですよ。
そんでCPUも著者から仕様が与えられてHDLで書いていくので、「アーキテクチャ何?x86_64?MIPS?」とか聞かれるとつらい、僕はnand2tetrisに出てくるCPUのアセンブラを書いている、それ以上でもそれ以下でもない。
ついでに言うとアセンブラの他にVMとか作るんですが、それらは読者の好きな言語で作る。 好き。 今回アセンブラはCで書きます。
Hackアセンブリ言語の仕様
読み返してみたら著者がnand2tetrisのアセンブリをHackアセンブリって呼んでました、じゃあアセンブラはHackアセンブラでいいですね、そう呼びます。
HackCPU1 の命令長は固定で16bitです。 またAレジスタ2とDレジスタ、Mレジスタ?3があります。
MのアドレスはAレジスタに入っている値です、変数みたいな扱いが出来ますね。
命令にはA命令とC命令の二種類、またシンボルが扱えます。
A命令はAレジスタの値を変更する命令で
@R1
とか@5
と書きます、この場合前者はR1に対応するアドレス、後者はAに5が代入されます。C命令は演算と分岐です、分岐先はAレジスタのアドレスになります。(分かり辛いですがシンボル使えばなんとなくわかります)
適当に書いてみるとこんな感じです。
@R1 M=1 D=1 (LOOP) D=D+1 A=D @LOOP 0;JMP
0;JMP
は無条件分岐なので上のコードではD=D+1
A=D
が無限ループします
他の命令は是非nand2tetrisを買って読んで下さい。
脳死で作ろう!!
Hackアセンブリ、よく出来てますね。
「えっ!?シンボルとかの機能あるのに脳死で作れるの!?」と驚いた方は安心して下さい、無理です。
今からこのよく出来たアセンブリを台無しにするんですよ?ゾクゾクしませんか?ゾクゾクしますね?
機能削ります、クソ削ります、鰹節です、生ハムの原木です。
仕様
- シンボル使えません
- A命令は
@R0
~@R15
のみ - コメント使用不可
実装の方針
NULL
実装
正直タイトルの出オチ感凄くないですか?
#include<stdio.h> #include<stdlib.h> #include<string.h> int main(int argc,char *argv[]){ FILE *bin_file,*asm_file; char bin_file_name[1024] = {"\0"}; char command[1024] = {"\0"}; char command_bin[1024] = {"\0"}; strcpy(bin_file_name,argv[1]); bin_file_name[strlen(bin_file_name) - 4] = '\0'; strcat(bin_file_name,".hack"); asm_file = fopen(argv[1],"r"); bin_file = fopen(bin_file_name,"w+"); if(asm_file == NULL || bin_file == NULL){ perror("[ERROR]\n"); exit(EXIT_FAILURE); } while(fgets(command,1024,asm_file) != NULL){ command[strlen(command) - 1] = '\0'; if(strcmp(command,"D=0") == 0){ strcpy(command_bin,"1110101010010000"); }else if(strcmp(command,"D=1") == 0){ strcpy(command_bin,"1110111111010000"); }else if(strcmp(command,"D=-1") == 0){ strcpy(command_bin,"1110111010010000"); }else if(strcmp(command,"D=D") == 0){ strcpy(command_bin,"1110110001100000"); }else if(strcmp(command,"D=A") == 0){ strcpy(command_bin,"1110110000010000"); }else if(strcmp(command,"D=!D") == 0){ strcpy(command_bin,"1110001101010000"); }else if(strcmp(command,"D=!A") == 0){ strcpy(command_bin,"1110110001010000"); }else if(strcmp(command,"D=-D") == 0){ strcpy(command_bin,"1110001111010000"); }else if(strcmp(command,"D=-A") == 0){ strcpy(command_bin,"1110110011010000"); }else if(strcmp(command,"D=D+1") == 0){ strcpy(command_bin,"1110011111010000"); }else if(strcmp(command,"D=A+1") == 0){ strcpy(command_bin,"1110110111010000"); }else if(strcmp(command,"D=D-1") == 0){ strcpy(command_bin,"1110001110010000"); }else if(strcmp(command,"D=A-1") == 0){ strcpy(command_bin,"1110110010010000"); }else if(strcmp(command,"D=D+A") == 0){ strcpy(command_bin,"1110000010010000"); }else if(strcmp(command,"D=D-A") == 0){ strcpy(command_bin,"1110010011010000"); }else if(strcmp(command,"D=A-D") == 0){ strcpy(command_bin,"1110000111010000"); }else if(strcmp(command,"D=D&A") == 0){ strcpy(command_bin,"1110000000010000"); }else if(strcmp(command,"D=D|A") == 0){ strcpy(command_bin,"1110010101010000"); }else if(strcmp(command,"D=M") == 0){ strcpy(command_bin,"1111110000010000"); }else if(strcmp(command,"D=!M") == 0){ strcpy(command_bin,"1111110001010000"); }else if(strcmp(command,"D=-M") == 0){ strcpy(command_bin,"1111110011010000"); }else if(strcmp(command,"D=M+1") == 0){ strcpy(command_bin,"1111110111010000"); }else if(strcmp(command,"D=M-1") == 0){ strcpy(command_bin,"1111110010010000"); }else if(strcmp(command,"D=D+M") == 0){ strcpy(command_bin,"1111000010010000"); }else if(strcmp(command,"D=D-M") == 0){ strcpy(command_bin,"1111010011010000"); }else if(strcmp(command,"D=M-D") == 0){ strcpy(command_bin,"1111000111010000"); }else if(strcmp(command,"D=D&M") == 0){ strcpy(command_bin,"1111000000010000"); }else if(strcmp(command,"D=D|M") == 0){ strcpy(command_bin,"1111010101010000"); }else if(strcmp(command,"A=0") == 0){ strcpy(command_bin,"1110101010100000"); }else if(strcmp(command,"A=1") == 0){ strcpy(command_bin,"1110111111100000"); }else if(strcmp(command,"A=-1") == 0){ strcpy(command_bin,"1110111010100000"); }else if(strcmp(command,"A=D") == 0){ strcpy(command_bin,"1110001100100000"); }else if(strcmp(command,"A=A") == 0){ strcpy(command_bin,"1110110000100000"); }else if(strcmp(command,"A=!D") == 0){ strcpy(command_bin,"1110001101100000"); }else if(strcmp(command,"A=!A") == 0){ strcpy(command_bin,"1110110001100000"); }else if(strcmp(command,"A=-D") == 0){ strcpy(command_bin,"1110001111100000"); }else if(strcmp(command,"A=-A") == 0){ strcpy(command_bin,"1110110011100000"); }else if(strcmp(command,"A=D+1") == 0){ strcpy(command_bin,"1110011111100000"); }else if(strcmp(command,"A=A+1") == 0){ strcpy(command_bin,"1110110111100000"); }else if(strcmp(command,"A=D-1") == 0){ strcpy(command_bin,"1110001110100000"); }else if(strcmp(command,"A=A-1") == 0){ strcpy(command_bin,"1110110010100000"); }else if(strcmp(command,"A=D+A") == 0){ strcpy(command_bin,"1110000010100000"); }else if(strcmp(command,"A=D-A") == 0){ strcpy(command_bin,"1110010011100000"); }else if(strcmp(command,"A=A-D") == 0){ strcpy(command_bin,"1110000111100000"); }else if(strcmp(command,"A=D&A") == 0){ strcpy(command_bin,"1110000000100000"); }else if(strcmp(command,"A=D|A") == 0){ strcpy(command_bin,"1110010101100000"); }else if(strcmp(command,"A=M") == 0){ strcpy(command_bin,"1111110000100000"); }else if(strcmp(command,"A=!M") == 0){ strcpy(command_bin,"1111110001100000"); }else if(strcmp(command,"A=-M") == 0){ strcpy(command_bin,"1111110011100000"); }else if(strcmp(command,"A=M+1") == 0){ strcpy(command_bin,"1111110111100000"); }else if(strcmp(command,"A=M-1") == 0){ strcpy(command_bin,"1111110010100000"); }else if(strcmp(command,"A=D+M") == 0){ strcpy(command_bin,"1111000010100000"); }else if(strcmp(command,"A=D-M") == 0){ strcpy(command_bin,"1111010011100000"); }else if(strcmp(command,"A=M-D") == 0){ strcpy(command_bin,"1111000111100000"); }else if(strcmp(command,"A=D&M") == 0){ strcpy(command_bin,"1111000000100000"); }else if(strcmp(command,"A=D|M") == 0){ strcpy(command_bin,"1111010101100000"); }else if(strcmp(command,"M=0") == 0){ strcpy(command_bin,"1110101010001000"); }else if(strcmp(command,"M=1") == 0){ strcpy(command_bin,"1110111111001000"); }else if(strcmp(command,"M=-1") == 0){ strcpy(command_bin,"1110111010001000"); }else if(strcmp(command,"D=D") == 0){ strcpy(command_bin,"1110001100001000"); }else if(strcmp(command,"M=A") == 0){ strcpy(command_bin,"1110110000001000"); }else if(strcmp(command,"M=!D") == 0){ strcpy(command_bin,"1110001101001000"); }else if(strcmp(command,"M=!A") == 0){ strcpy(command_bin,"1110110001001000"); }else if(strcmp(command,"M=-D") == 0){ strcpy(command_bin,"1110001111001000"); }else if(strcmp(command,"M=-A") == 0){ strcpy(command_bin,"1110110011001000"); }else if(strcmp(command,"M=D+1") == 0){ strcpy(command_bin,"1110011111001000"); }else if(strcmp(command,"M=A+1") == 0){ strcpy(command_bin,"1110110111001000"); }else if(strcmp(command,"M=D-1") == 0){ strcpy(command_bin,"1110001110001000"); }else if(strcmp(command,"M=A-1") == 0){ strcpy(command_bin,"1110110010001000"); }else if(strcmp(command,"M=D+A") == 0){ strcpy(command_bin,"1110000010001000"); }else if(strcmp(command,"M=D-A") == 0){ strcpy(command_bin,"1110010011001000"); }else if(strcmp(command,"M=A-D") == 0){ strcpy(command_bin,"1110000111001000"); }else if(strcmp(command,"M=D&A") == 0){ strcpy(command_bin,"1110000000001000"); }else if(strcmp(command,"M=D|A") == 0){ strcpy(command_bin,"1110010101001000"); }else if(strcmp(command,"M=M") == 0){ strcpy(command_bin,"1111110000001000"); }else if(strcmp(command,"M=!M") == 0){ strcpy(command_bin,"1111110001001000"); }else if(strcmp(command,"M=-M") == 0){ strcpy(command_bin,"1111110011001000"); }else if(strcmp(command,"M=M+1") == 0){ strcpy(command_bin,"1111110111001000"); }else if(strcmp(command,"M=M-1") == 0){ strcpy(command_bin,"1111110010001000"); }else if(strcmp(command,"M=D+M") == 0){ strcpy(command_bin,"1111000010001000"); }else if(strcmp(command,"M=D-M") == 0){ strcpy(command_bin,"1111010011001000"); }else if(strcmp(command,"M=M-D") == 0){ strcpy(command_bin,"1111000111001000"); }else if(strcmp(command,"M=D&M") == 0){ strcpy(command_bin,"1111000000001000"); }else if(strcmp(command,"M=D|M") == 0){ strcpy(command_bin,"1111010101001000"); }else if(strcmp(command,"MD=0") == 0){ strcpy(command_bin,"1110101010011000"); }else if(strcmp(command,"MD=1") == 0){ strcpy(command_bin,"1110111111011000"); }else if(strcmp(command,"MD=-1") == 0){ strcpy(command_bin,"1110111010011000"); }else if(strcmp(command,"MD=D") == 0){ strcpy(command_bin,"1110001100011000"); }else if(strcmp(command,"MD=A") == 0){ strcpy(command_bin,"1110110000011000"); }else if(strcmp(command,"MD=!D") == 0){ strcpy(command_bin,"1110001101011000"); }else if(strcmp(command,"MD=!A") == 0){ strcpy(command_bin,"1110110001011000"); }else if(strcmp(command,"MD=-D") == 0){ strcpy(command_bin,"1110001111011000"); }else if(strcmp(command,"MD=-A") == 0){ strcpy(command_bin,"1110110011011000"); }else if(strcmp(command,"MD=D+1") == 0){ strcpy(command_bin,"1110011111011000"); }else if(strcmp(command,"MD=A+1") == 0){ strcpy(command_bin,"1110110111011000"); }else if(strcmp(command,"MD=D-1") == 0){ strcpy(command_bin,"1110001110011000"); }else if(strcmp(command,"MD=A-1") == 0){ strcpy(command_bin,"1110110010011000"); }else if(strcmp(command,"MD=D+A") == 0){ strcpy(command_bin,"1110000010011000"); }else if(strcmp(command,"MD=D-A") == 0){ strcpy(command_bin,"1110010011011000"); }else if(strcmp(command,"MD=A-D") == 0){ strcpy(command_bin,"1110000111011000"); }else if(strcmp(command,"MD=D&A") == 0){ strcpy(command_bin,"1110000000011000"); }else if(strcmp(command,"MD=D|A") == 0){ strcpy(command_bin,"1110010101011000"); }else if(strcmp(command,"MD=M") == 0){ strcpy(command_bin,"1111110000011000"); }else if(strcmp(command,"MD=!M") == 0){ strcpy(command_bin,"1111110001011000"); }else if(strcmp(command,"MD=-M") == 0){ strcpy(command_bin,"1111110011011000"); }else if(strcmp(command,"MD=M+1") == 0){ strcpy(command_bin,"1111110111011000"); }else if(strcmp(command,"MD=M-1") == 0){ strcpy(command_bin,"1111110010011000"); }else if(strcmp(command,"MD=D+M") == 0){ strcpy(command_bin,"1111000010011000"); }else if(strcmp(command,"MD=D-M") == 0){ strcpy(command_bin,"1111010011011000"); }else if(strcmp(command,"MD=M-D") == 0){ strcpy(command_bin,"1111000111011000");
中略
}else if(strcmp(command,"D+M;JGT") == 0){ strcpy(command_bin,"1111000010000001"); }else if(strcmp(command,"D-M;JGT") == 0){ strcpy(command_bin,"1111010011000001"); }else if(strcmp(command,"M-D;JGT") == 0){ strcpy(command_bin,"1111000111000001"); }else if(strcmp(command,"D&M;JGT") == 0){ strcpy(command_bin,"1111000000000001"); }else if(strcmp(command,"D|M;JGT") == 0){ strcpy(command_bin,"1111010101000001"); }else if(strcmp(command,"0;JEQ") == 0){ strcpy(command_bin,"1110101010000010"); }else if(strcmp(command,"1;JEQ") == 0){ strcpy(command_bin,"1110111111000010"); }else if(strcmp(command,"-1;JEQ") == 0){ strcpy(command_bin,"1110111010000010"); }else if(strcmp(command,"A;JEQ") == 0){ strcpy(command_bin,"1110110000000010"); }else if(strcmp(command,"!D;JEQ") == 0){ strcpy(command_bin,"1110001101000010"); }else if(strcmp(command,"!A;JEQ") == 0){ strcpy(command_bin,"1110110001000010"); }else if(strcmp(command,"-D;JEQ") == 0){ strcpy(command_bin,"1110001111000010"); }else if(strcmp(command,"-A;JEQ") == 0){ strcpy(command_bin,"1110110011000010"); }else if(strcmp(command,"D+1;JEQ") == 0){ strcpy(command_bin,"1110011111000010"); }else if(strcmp(command,"A+1;JEQ") == 0){ strcpy(command_bin,"1110110111000010"); }else if(strcmp(command,"D-1;JEQ") == 0){ strcpy(command_bin,"1110001110000010"); }else if(strcmp(command,"A-1;JEQ") == 0){ strcpy(command_bin,"1110110010000010"); }else if(strcmp(command,"D+A;JEQ") == 0){ strcpy(command_bin,"1110000010000010"); }else if(strcmp(command,"D-A;JEQ") == 0){ strcpy(command_bin,"1110010011000010"); }else if(strcmp(command,"A-D;JEQ") == 0){ strcpy(command_bin,"1110000111000010"); }else if(strcmp(command,"D&A;JEQ") == 0){ strcpy(command_bin,"1110000000000010"); }else if(strcmp(command,"D|A;JEQ") == 0){ strcpy(command_bin,"1110010101000010"); }else if(strcmp(command,"M;JEQ") == 0){ strcpy(command_bin,"1111110000000010"); }else if(strcmp(command,"!M;JEQ") == 0){ strcpy(command_bin,"1111110001000010"); }else if(strcmp(command,"-M;JEQ") == 0){ strcpy(command_bin,"1111110011000010"); }else if(strcmp(command,"M+1;JEQ") == 0){ strcpy(command_bin,"1111110111000010"); }else if(strcmp(command,"M-1;JEQ") == 0){ strcpy(command_bin,"1111110010000010"); }else if(strcmp(command,"D+M;JEQ") == 0){ strcpy(command_bin,"1111000010000010"); }else if(strcmp(command,"D-M;JEQ") == 0){ strcpy(command_bin,"1111010011000010"); }else if(strcmp(command,"M-D;JEQ") == 0){ strcpy(command_bin,"1111000111000010"); }else if(strcmp(command,"D&M;JEQ") == 0){ strcpy(command_bin,"1111000000000010"); }else if(strcmp(command,"D|M;JEQ") == 0){ strcpy(command_bin,"1111010101000010"); }else if(strcmp(command,"@R0") == 0){ strcpy(command_bin,"0000000000000000"); }else if(strcmp(command,"@R1") == 0){ strcpy(command_bin,"0000000000000001"); }else if(strcmp(command,"@R2") == 0){ strcpy(command_bin,"0000000000000010"); }else if(strcmp(command,"@R3") == 0){ strcpy(command_bin,"0000000000000011"); }else if(strcmp(command,"@R4") == 0){ strcpy(command_bin,"0000000000000100"); }else if(strcmp(command,"@R5") == 0){ strcpy(command_bin,"0000000000000101"); }else if(strcmp(command,"@R6") == 0){ strcpy(command_bin,"0000000000000110"); }else if(strcmp(command,"@R7") == 0){ strcpy(command_bin,"0000000000000111"); }else if(strcmp(command,"@R8") == 0){ strcpy(command_bin,"0000000000001000"); }else if(strcmp(command,"@R9") == 0){ strcpy(command_bin,"0000000000001001"); }else if(strcmp(command,"@R10") == 0){ strcpy(command_bin,"0000000000001010"); }else if(strcmp(command,"@R11") == 0){ strcpy(command_bin,"0000000000001011"); }else if(strcmp(command,"@R12") == 0){ strcpy(command_bin,"0000000000001100"); }else if(strcmp(command,"@R13") == 0){ strcpy(command_bin,"0000000000001101"); }else if(strcmp(command,"@R14") == 0){ strcpy(command_bin,"0000000000001110"); }else if(strcmp(command,"@R15") == 0){ strcpy(command_bin,"0000000000001111"); } command_bin[strlen(command_bin)] = '\n'; fputs(command_bin,bin_file); } fclose(asm_file); fclose(bin_file); return 0; }
脳死で書けましたね? おめでとうございます。
明日は友達に「僕はアセンブラ書きましたけど、あなたは?」 と煽りましょう。
まとめ
いかがでしたか?
nand2tetrisは良いです
またネタ思いついたらなんか書きます