脳死で作る!クソ低機能アセンブラ

ネットコンテンツへようこそ これやります

アセンブラ is 何

アセンブリをバイナリに変換するやつです、出たバイナリをCPUが食べて(人類が)幸せになります。

何相手のアセンブラ作るの?

そう、これが問題。 CPUが違えばアセンブリも違う、怖い、言オリかよ。

詳しくは以下の素晴らしい本が出てるので買いましょう、買いましょう

大熱血! アセンブラ入門

大熱血! アセンブラ入門

だから何相手のアセンブラ作るの??

コンピュータシステムの理論と実装という本がある。(通称 nand2tetris)

Nandゲートから各種ゲート、そっからALU、なんやかんやあってCPU、OS作ってテトリス動かそうぜ!

そんな本です。 エモいですね?楽しそうですね? 買いましょう作りましょう、そんで教えて下さい。

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

で?

そう、それでですね、この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は良いです

またネタ思いついたらなんか書きます


  1. nand2tetrisのCPU

  2. レジスタはCPUにあるポケットみたいな認識でいいです(最高の例え

  3. レジスタと呼んではいけない気がする