進学先決定


昨日東京農工大学後期試験の合格発表がなされ、情報工学科に受かったようです。

去年、今年と二年連続で東京工業大学を受験しましたが、合格点には達さなかったようで残念な結果に終わってしまいました。

そこで農工大に拾ってもらい、これも何かの縁だと思って4年間この大学に通うことにしました。

 

・・・ふつう浪人生っていっぱい私立大学も受験するものだよね?

私立大学一校しか受けなかったくせに補欠で繰り上がりもなしというねwwwww

 

まぁそんなこんなで進学先が決まったので、ブログのサブタイトルも『東工大志望の日常』から『農工大生の日常』に変更します。

では、これからもよろしくお願いしますっ!ノシ

BrainfuckインタプリタをAssemblyで書き直してみた。


先日の池袋バイナリ勉強会に行ったときの記事を覚えてますでしょうか?

バイナリ勉強会#1

ここにあるようにC++でBrainfuckのインタプリタを書いたのですが、このコードをコンパイルした実行ファイルの大きさがゆうに100kBいってしまっていて、もっと軽くならないものかと思ってたんですよね・・・

 

そこで、今回はBrainfuckのインタプリタをAssembly言語で最初から書き直してみました。

それではどうぞ!


;Brainfuck.asm
 bits 16
 org 100h

;メモリ初期化
 mov cx,799h
set: mov bx,cx
 mov byte [mem+bx],0
 loop set

;コード変換
 mov ah,09h
 mov dx,msg0
 int 21h
 mov ah,01h
 int 21h
 sub al,30h
 mov byte [cvt],al

;Inputメッセージ
 mov ah,09h
 mov dx,crlf
 int 21h
 mov dx,msg1
 int 21h
 mov dx,crlf
 int 21h

;Brainfuckコード入力
 mov ah,01h
input: int 21h
 cmp al,0dh
 jz domsg
 inc word [len]
 mov bx,[len]
 mov byte [cmd+bx],al
 jmp input

;コード実行
domsg: mov ah,09h
 mov dx,crlf
 int 21h
 mov dx,msg2
 int 21h
 mov dx,crlf
 int 21h

main: inc word [cps]
 mov bx,[cps]

cmp byte [cmd+bx],'-'
 jz decr

cmp byte [cmd+bx],'>'
 jz next

cmp byte [cmd+bx],'<'
 jz back

cmp byte [cmd+bx],','
 jz getc

cmp byte [cmd+bx],'.'
 jz putc

;変換分岐
 cmp byte [cvt],1
 jz cnvrt

;変換不必要
 cmp byte [cmd+bx],'+'
 jz incr

cmp byte [cmd+bx],'['
 jz lin

cmp byte [cmd+bx],']'
 jz lout

;変換必要
cnvrt: cmp byte [cmd+bx],':'
 jz incr

cmp byte [cmd+bx],']'
 jz lin

cmp byte [cmd+bx],'\'
 jz lout

done: mov bx,[mps]
 cmp byte [mem+bx],0
 js err
 cmp word [mps],0
 js err
 mov dx,[len]
 cmp [cps],dx
 js main
 mov ax,4c00h
 int 21h

;エラー処理
err: mov ah,09h
 mov dx,msg3
 int 21h
 mov ax,4c00h
 int 21h

;+
incr: mov bx,[mps]
 inc byte [mem+bx]
 jmp done

;-
decr: mov bx,[mps]
 dec byte [mem+bx]
 jmp done

;>
next: inc word [mps]
 jmp done

;<
back: dec word [mps]
 jmp done

;.
putc: mov bx,[mps]
 mov dl,[mem+bx]
 mov ah,02h
 int 21h
 jmp done

;,
getc: mov ah,08h
 int 21h
 mov bx,[mps]
 mov byte [mem+bx],al
 jmp done

;[
lin: mov bx,[mps]
 cmp byte [mem+bx],0
 jz skip
 mov bx,[cps]
 push bx
 jmp done

skip: inc word [cps]
 mov bx,[cps]
 ;変換分岐
 cmp byte [cvt],1
 jz scnvrt
 ;変換不要
 cmp byte [cmd+bx],'['
 jz li
 cmp byte [cmd+bx],']'
 jz ld
 ;変換必要
scnvrt: cmp byte [cmd+bx],']'
 jz li
 cmp byte [cmd+bx],'\'
 jz ld
 jmp skip

li: inc byte [lev]
 jmp skip

ld: cmp byte [lev],0
 jz done
 dec byte [lev]
 jmp skip

;]
lout: pop bx
 mov word [cps],bx
 dec word [cps]
 jmp done

msg0 db "Do you need convert code? (Y:1,N:other)>>$"
msg1 db "Input Brainfuck code!$"
msg2 db "Output$"
msg3 db "Error!!$"
crlf db 0dh,0ah,"$"
cvt db 0
cmd resb 800h
cps dw 0
mem resb 800h
mps dw 0
len dw 0
lev db 0

ソースコードは多少長く長くなりましたが、実行ファイルの大きさはなんと4.5kB!びっくりするほど小さくなりました~

あ、でもここでは命令用・実行用メモリをそれぞれ0x800個、つまり十進数で2048個取っているのですが、Brainfuckの仕様通りに実行用メモリの数を30000個取るようにすると30kBほどに膨れ上がってしまうんです。その代わり、やはり演算は相変わらずめちゃくちゃ早いですw

ダウンロードは先日と同様こちらからどうぞ。Brainfuckインタプリタ

 

また来週くらいに同様の勉強会があるようなので、続きをやりに行こうと思います!!

全受験を終える


本日東京農工大学の後期日程の受験を終え、これで今期の全ての受験が終わりました。

後期を受けたと言うことは・・・

東京工業大学とはご縁が無かったのかなorz ということです。

 

今回の合否結果が出るのは今月21日のようですので、この事についてはそのときにまた報告します。

 

ひとまず暫くはしなければならないことは無くなったので、禁書目録とかレ・ミゼラブルとか見てきますww

あと、また色々コンピュータの勉強していこうと思うので、これからもよろしくお願いします!!

バイナリ勉強会 #1


池袋で行われているバイナリ勉強会に初めて、友人と参加させて頂きました。

確か去年も一緒に前期試験が終わった直後に勉強会に参加して、その時は八王子まで出向いた気がします。でもそこでの勉強会は失敗だったんだよな・・・orz

まぁそんな前のことはどうでもいいのですねww

 

まずは大体半年程度を通してのカリキュラムを見せて頂きました。

基礎編ではBrainf*ckのインタプリタの自作から始まり、Cコンパイラの自作、UNIX V6でカーネル入門等々と続きます。

今日はその第一回なので、最初の最初にGtk#(初耳)でBrainf*ckのインタプリタをC#で作ります。

C#初めてで大丈夫かな・・・?とか思ったのですが、指示に従って進めていくとJavaの先代だけあって結構似通ったところがあって理解も進みます。

 

ひとまずこれがほとんど完成したところで昼食をはさんで後半戦に望みます。

お次の指示は、自分の好きな言語で何でもいいのでファイルから読み込んでBrainf*ckのインタプリタを作れとのこと。

ここで最初はC言語で作ろうと思ったのですが、気がついたら何故かC++で作ってましたww

 

今更なのですが、ここでBrainfuckの仕様を説明します。(引用:wikipedia Brainfuck

処理系は次の要素から成る: Brainfuckプログラム、インストラクションポインタ(プログラム中のある文字を指す)、少なくとも30000個の要素を持つバイトの配列(各要素はゼロで初期化される)、データポインタ(前述の配列のどれかの要素を指す。最も左の要素を指すよう初期化される)、入力と出力の2つのバイトストリーム。

Brainfuckプログラムは、以下の8個の実行可能な命令から成る(他の文字は無視され、読み飛ばされる)。

  1. >: ポインタをインクリメントする。ポインタをptrとすると、C言語の「ptr++;」に相当する。
  2. <: ポインタをデクリメントする。C言語の「ptr--;」に相当。
  3. +: ポインタが指す値をインクリメントする。C言語の「(*ptr)++;」に相当。
  4. -: ポインタが指す値をデクリメントする。C言語の「(*ptr)--;」に相当。
  5. .: ポインタが指す値を出力に書き出す。C言語の「putchar(*ptr);」に相当。
  6. ,: 入力から1バイト読み込んで、ポインタが指す先に代入する。C言語の「*ptr=getchar();」に相当。
  7. [: ポインタが指す値が0なら、対応する ] の直後にジャンプする。C言語の「while(*ptr){」に相当。
  8. ]: ポインタが指す値が0でないなら、対応する [ (の直後)にジャンプする。C言語の「}」に相当。

 

・・・開発始める前にちゃんと仕様読めば良かったなぁ。最初[には絶対に一回は入るように作っちゃうから失敗するんだよねww

そんな感じでなんだかんだで完成したのが以下になります。数ヶ月ぶりのちゃんとしたコーディングなので、完全に感覚が鈍っててコードが汚いのは勘弁してください。

#include <iostream>
#include <fstream>
#include <cstdio>

using namespace std;

void func(char[],char[],int*,int*,int*);
int loop[128]={};

int main(void){
 ifstream ifs;
 char c,cmd[2048]={},mem[30000]={};
 int i=0,cps=0,mps=0,lps=0;

 ifs.open("text.bf",ios::in);

 if(!ifs){
  cout << "ファイルが存在しません。" << endl;
  return -1;
 }

 for(i=0;!ifs.eof();i++){
  ifs.get(c);
  cmd[i]=c;
 }
 while(cps<i-1)
  func(cmd,mem,&cps,&mps,&lps);

 ifs.close();
 return 0;
}

void func(char cmd[],char mem[],int *cps,int *mps,int *lps){
 int lev = 0;

 switch(cmd[*cps]){
  case '>':
   ++*mps;
   break;

  case '<':
   --*mps;
   break;

  case '+':
   ++mem[*mps];
   break;

  case '-':
   --mem[*mps];
   break;

  case '[':
   if(mem[*mps]>0){
    ++*lps;
    loop[*lps]=*cps;
   }
   else{
    int lev=1;

    do{
     ++*cps;
     switch(cmd[*cps]){
      case '[':
       ++lev;
       break;

      case ']':
       --lev;
       break;
     }
    }while(lev!=0||cmd[*cps]!=']');

   }
   break;

  case ']':
   if(mem[*mps]>0)
    *cps=loop[*lps];
   else
    --*lps;
   break;

  case '.':
   cout << mem[*mps];
   break;

  case ',':
   mem[*mps]=getchar();
   break;
  }
  ++*cps;
}

ここで初めは","に対して『cin >> mem[*mps]』を使ってたのですが、これだと改行コードが含まれないことが判明したのでgetchar()にしました。
途中break文ごとコメントアウトして何で正常に動かないのだろうとかいうミスをやらかしたりしましたが、結果的に完成したのでよしとしましょう。
ここに完成品を置いておきますね。これはファイル読み込みではなく標準入力にしておきます。

Brainfuckインタプリタ

さて、一通り済んだところで残り時間もわずかになりましたが、次の講座のためにMinGWを準備してbinutilsのインストールまでやっておきます。
・・・ただここで『性能の違い』というものを見せ付けられました。自分のほう(Atom)が先にビルト始めたのに、友人のPC(i5)の方が完全に先に処理を終えるというwwww

 

まぁこんな感じで久しぶりに良い勉強会に当たったようなので、これから常連さんにでもなろうかと思っています。

これからもよろしくお願いします!