アセンブラ編 入替えプログラム ~できた~
8086
"コンピュータのしくみを理解するための10章"のASCアセンブラでプログラムを考えようと思いましたが、8086との違いが大きいのではじめから8086アセンブラで考えます。
はじめに思いついたのは、前に考えた回路を、ANDとORとNOTの命令で作ることです。
だけど、これだと"program"は逆さまにできても、"tomato"はできません。
"tomato"にはまた別のプログラムがいります。
細山田さんのやつのように、キーボードで単語を打ち込んで、それを逆さまに表示するようなのにしたいです。
プログラムの流れを、
- キーボードからの単語をメモリに入れる。
- メモリを逆さまに読み出して画面に出す。
にわけて考えます。
まず、キーボードからの単語をメモリに入れる命令を調べました。
押されたキーを読み取る命令はint 16hです。アスキーコードがalに入ります。
ストアの命令はmovです。ASCと違いレジスタが複数あるので指定しないといけません。
次に、メモリを読み出して画面に出す命令を調べました。
ロードの命令はmovです。なぜかストアと同じです。
画面に文字を出す命令はint 10hです。alにアスキーコードを入れておきます。
肝心の"逆さまに"は、単語のメモリアドレスを後ろから読むことでやります。
レジスタdiの間接アドレス指定を使いました。
レジスタdiに単語の最後の文字のアドレスを入れておきます。
読み取るときには、diの指定するアドレスの指定する文字データを画面に表示させて、そのたびにdiを減らし、これを先頭の文字まで繰り返します。
あとは、8086のためのおまじないが必要になります。
コードの開始アドレスが7c00hに決められています。疑似命令orgで指定します。
コードの大きさが512バイトに決められています。埋め草を入れます。
コードの終わりの2バイトはaa55hに決められています。
自由に使えるメモリの位置が決められています。7e00hを使います。
できあがったプログラムです。
org 0x7c00 bits 16 cli xor ax, ax mov ds, ax mov si, 0x7e00 mov di, si yomitori: mov ah, 0x00 int 0x16 mov ah, 0x0e int 0x10 cmp al, 0x0d jz irekae cmp al, 0x08 jz .backspace mov [di], al inc di jmp yomitori .backspace cmp di, si jz yomitori mov ax, 0x0a20 mov cx, 0x01 int 0x10 mov BYTE [di], 0x00 dec di jmp yomitori kaigyo: mov ah, 0x03 int 0x10 mov ah, 0x02 mov dl, 0x00 inc dh int 0x10 ret irekae: cmp di, si jz yomitori call kaigyo mov ah, 0x0e .hyouji: dec di mov al, [di] int 0x10 cmp di, si jnz .hyouji call kaigyo jmp yomitori times 510-($-$$) db 0 dw 0xaa55
"コンピュータのしくみを理解するための10章"にキーボードエコーがあるとよいと書かれていたので、yomitoriに足しました。
見やすくするために、単語や逆さま単語ごとに改行することにしました。
あと、はてな記法は7c00hだと変な色になるので0x7c00にしました。
scheme(の動かないプログラム)よりもずいぶん長くなりました。
でも、yomitoriやkaigyoの分が長いだけで、irekaeのところは同じぐらいです。
さっそく実行します。
もらったメモを見ながらアセンブリ言語を機械語にします。
> yasm irekae.asm
機械語のファイルをフロッピーかCD-Rに書き込みます。
> dd if=/dev/zero of=floppy bs=1024 count=1440 > dd if=irekae of=floppy seek=0 count=1 conv=notrunc
ノートパソコンにはフロッピーはないのでCD-RWにします。
> cp floopy boot/ > mkisofs -input-charset iso8859-1 -o cdr.iso -b floppy -hide floppy boot/ > cdrecord dev=/dev/sr0 blank=fast -data cdr.iso
CDを入れたままパソコンを再起動するとガコガコいって入替えプログラムが始まります。
program⏎と打ち込むとmargorpが表示されます。
tomato⏎もotamotになりました。
できました!!
満足したので電源ボタンを長押しして終了させました。☠
アセンブラ編 前回の反省
まず、前回の失敗の原因を考えてみました。
原因は、たぶん、プログラムの論理回路を作ろうとしたことでしょう。
回路を考えても、その回路をコンピュータに足すことはできないようです。
はじめから入っている回路の命令を組み合わせてプログラムの回路にしないといけません。
配られたカードで勝負するタイプです。
細山田さんに、ジャバで作った入替えプログラムのお手本を見せてもらいました。
お手本では、キーボードでprogramと打つと、画面にmargorpと表示されます。
さらに、tomatoだとotamotになります。
ジャバのプログラムも見せてもらいましたが、よく分かりませんでした。
アセンブラ言語で同じものを作ります。
ノートパソコンで使える命令を調べました。
ノートパソコンの命令は、AMD64というやつで、たくさんありました。
AMD64は64bitですが、32bitと16bitの命令も入っています。
"コンピュータのしくみを理解するための10章"の例が16bitなので、16bitにします。
16bitの命令は、8086といいます。これなら、"コンピュータのしくみを理解するための10章"にも書いてました。
入替えプログラムができるぐらいには、8086を憶えることにします。
Scheme編 入替えプログラム ~動かない~
Lispのひとの話からプログラムに必要なところを抜き出します。
まずは、Conditional Expressionsについてです。
(p₁ → e₁, ⋯ , pₙ → eₙ)がconditional expressionsのかたちです。
pは、propositional expressionsでeは任意のexpressionsです。
次は、S-expressionsについてです。
Atomic symbolsはS-expressionsです。
Atomic symbolsには、大文字と数字とそれらに埋め込まれた空白とからなる文字列が使われます。
e₁とe₂がS-expressionsなら(e₁∙e₂)もS-expressionsです。
(∙)はordered pairです。
次は、Listについてです。
リストは、S-expressionsで表現できます。
(m₁, m₂, ⋯, mₙ)は
(m₁∙(m₂∙(⋯(mₙ∙NIL)⋯)))になります。
NILはatomic symbolで、Listの終端に使われます。
最後は、functionsについてです。
functionsは、普通の記法で書きます。ただし、S-expressionsの関数と区別するために名前と変数は小文字にし、()を[]に、,を;にします。これをM-expessionsといいます。
eq [x; y]は、xとyがatomicのときに定義され、xとyが同じsymbolならT、違うならFです。
car [x]は、xがatomicでないときに定義されます。car [(e₁∙e₂)] = e₁です。
cdr [x]は、xがatomicでないときに定義されます。cdr [(e₁∙e₂)] = e₂です。
cons [x; y]は、任意のxとyについて定義されます。cons [e₁; e₂]= (e₁∙e₂)です。
こうやってまとめて書くと、かしこくなった気がしますが、実際には、ただ写しているだけで、よく分かっていません。
さて、実際にプログラムを作ってみます。
入れ替えを手でやるときは、"program"の後ろから一文字づつ順番に書いていきます。
これをLispの形にすると・・・一番後ろの文字を取り出した残りがうまく作れません。
発想を転換して、"program"の前から一文字づつ取り出して逆さまに並べることにします。
入れ替えのfunctionをirekaeとすると、
irekae [x; y] = (eq [x; NIL] → y, T → irekae [cdr [x]; cons [car [x]; y])
Church's λ-notationにより、
irekae = λ[[x; y]; (eq [x; NIL] → y, T → irekae [cdr [x]; cons [car [x]; y])]
irekaeはirekaのなかにでてくるので、
label [irekae; λ[[x; y]; (eq [x; NIL] → y, T → irekae [cdr [x]; cons [car [x]; y])]]
これに、programを代入すると、
label [irekae; λ[[x; y]; (eq [x; NIL] → y, T → irekae [cdr [x]; cons [car [x]; y])]][[(P∙ (R∙ (O∙ (G∙ (R∙ (A∙ (M∙ NIL))))))); NIL]]
M-expressionsをS-expressionsに訳すと、
((LABEL, IREKAE, (LAMBDA, (X, Y), (COND, ((EQ, X, NIL), Y), (T, (IREKAE, (CDR, X), (CONS, (CAR, X), Y)))))), ((P,R,O,G,R,A,M), NIL))
さっそくschemeに入れてみたいと思います。
もらったメモを見ながら、
> busybox ed : a [S-expressionsを入れます] . : w irekae : q > sbcl --load irekae
なんだか英語がたくさんでてきてよくわかりませんが、うまく動いてないことだけは確かです。
こうなるかもと思ってましたのでショックはありません。本当です。
LispとSchemeは、古典と現代文みたいに違うのかもしれません。
Schemeは一休みです。
"コンピュータのしくみを理解するための10章"の読書が進み、内容が少し理解できるようになったので、アセンブラ言語に戻りたいと思います。
Scheme編
"コンピュータのしくみを理解するための10章"には、Schemeのことは載ってません。
また、近くの書店にも関連する本は置いてませんでした。
しかし、幸いなことにネットにLISPを作った人の書いた話がありましたので、それを読むことにしました。
アセンブラ言語を挫折したこと、Lispを始めたことを話しました。こころなしか皆が遠い目をしてました。
めずらしく石丸が話にのってきました。
Lispは、"すべてがFになる"というアニメに出てくるそうです。
Lispの人の話は、途中で挫折しました。内容は、"コンピュータのしくみを理解するための10章"よりも難しく、ちっとも理解できませんでした。
でもプログラムのやりかたは例をみてなんとなくわかった気がするので、入替えプログラムに挑戦したいと思います。
アセンブラ編 入替えプログラムの作成
入替えプログラムの作成
"コンピュータのしくみを理解するための10章"の3章に、足し算の例が書かれているので、これを参考にすすめたいと思います。
まずは、"program"と"margorp"の対応表を作ります。
p | r | o | g | r | a | m |
↓ | ↓ | ↓ | ↓ | ↓ | ↓ | ↓ |
m | a | r | g | o | r | p |
次に、"program"を2進数で表します。図5.29の文字コードと照らし合わせると、
p | 0111 | 0000 |
r | 0111 | 0010 |
o | 0110 | 1111 |
g | 0110 | 0111 |
r | 0111 | 0010 |
a | 0110 | 0001 |
m | 0110 | 1101 |
になります。
次に、真理値表を作るのですが、'r'の入替え先が'a'と'o'の2つあって真理値表ができません。
しかたないので、2つめの'r'は大文字にすることにしました。Rの文字コードは、
R | 0101 | 0010 |
です。
真理値表は、
入力 | 出力 | ||
p | 01110000 | 01101101 | m |
r | 01110010 | 01100001 | a |
o | 01101111 | 01110010 | R |
g | 01100111 | 01100111 | g |
R | 01110010 | 01101111 | o |
a | 01100001 | 01110010 | r |
m | 01101101 | 01110000 | p |
になります。
真理値表をよく見ると、入力も出力も始めは"011"で変化していません。なので、省略することにします。
さらに、入力の各ビットにA0~A4、出力の各ビットにZ0~Z4と名前を付けます。
新しい真理値表は、
A0 | A1 | A2 | A3 | A4 | Z0 | Z1 | Z2 | Z3 | Z4 |
1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 |
1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |
0 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 0 |
0 | 0 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 1 |
1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 1 | 1 |
0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 |
0 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
です。
この真理値表から論理式を作ります。ですが、また問題です。和+と積・の記号はありましたが、否定の上線の記号がありません。
しかたがないので、否定にしました。これで論理式は、
Z0 = A0・A1・A2・A3・A4+A0・A1・A2・A3・A4+A0・A1・A2・A3・A4
Z1 = A0・A1・A2・A3・A4+A0・A1・A2・A3・A4
Z2 = A0・A1・A2・A3・A4+A0・A1A2・A3・A4+A0・A1・A2・A3・A4
Z3 = A0・A1・A2・A3・A4+A0・A1・A2・A3・A4+A0・A1・A2・A3・A4+A0・A1・A2・A3・A4
Z4 = A0・A1・A2・A3・A4+A0・A1・A2・A3・A4+A0・A1・A2・A3・A4+A0・A1・A2・A3・A4
となります。
この論理式を論理回路にします。入力も出力も5つなので線が多くて大変です。
お披露目
さっそく、細山田さんに見せましたが、
「えっ?これってプログラムじゃないですよね」とのお答え。
曽根も「この絵でコンピュータ動かせるんか?」と生意気です。
動作を説明してみましたが、どうもしっくりこない様子でした。
いわれてみれば、プログラミングなのに「回路ができました!」ではおかしいかもしれません。
アセンブラ編
お題
目標が欲しかったので、お題を出してもらいました。
曽根「BMIを計算する。日本の有名な天才ハッカーもこれから始めた。」
細山田さん「文字列の順番を入れ替える。例えば、"program"を"margorp"に」
石丸「??...」
BMIは、難しそうなので、まずは細山田さんの入れ替えプログラムから作ります。
参考書
さて、はりきってコンピュータに向いましたが、何から手をつけてよいのかさっぱり分かりません。
ウェブで"アセンブラ 入門"を検索すると、入門サイトがでてきますが、入門とは思えない内容ばかりです。
アセンブラだけでなくコンピュータの基礎知識も足りてないようなので入門書を買うことにしました。
書店でコンピュータ関連の本を探すと、小学生向けのプログラミング本がありました。イラストが多くて内容も易しそうでした。
しかし、アセンブラについて書かれているものはありませんでした。
しかたなく、アセンブラについて記されているもののなかから選ぶことにしました。
イラストの多さを基準に"コンピュータのしくみを理解するための10章"馬場敬信を買うことにしました。
給料泥棒
"コン~10章"をパラパラとめくってみましたが、大学生向けなのか内容が難しく半分も理解できませんでした。
ただ、図7.1の"仕事をしてない"上司は、とても気に入りました。
この本は、プログラミングの学習とともに徐々に読みすすめたいと思います。
パソコン
序
ノートパソコンをもらったので、ブログを始めることにしました。その話題作りのために、まえから興味があったプログラミングを憶えることにしました。
プログラミング言語の選択
まずは、計算尺部でおすすめの言語を聞いてみました。
曽根「パイソンがええんちゃうか?」
細山田さん「ジャバですね」
石丸「はぁ…」
次に、ネットで調べました。たくさんの言語があったので、候補を選ぶための基準を考えました。
選択の基準
- お金
プログラミング言語には有料なのと無料なのとがあることが分かりました。お金がないので、ただのものを選びたいと思います。
- かっこよさ
挫折しそうなときでも、言語がかっこいいとがんばれる気がします。かっこいいのを選びたいと思います。
候補
- ジャバ
長所:細山田さんのおすすめ。
短所:普及率が高く、皆が使っているのでかっこよくない。
- C
長所:本があった。
短所:呼びにくい。
- Fortan
長所:真のハッカーが使うらしい。かっこいい。
短所:科学技術計算に使う例ばかりで、真のハッカーが使っている情報がない。
長所:名前が偉そう。
短所:真のハッカーは使わない。
長所:長い歴史、高い意識。
短所:初心者お断り。
長所:カテゴリー論がどうのこうので何かかっこいい。
短所:ウェブの情報は、横文字が多くて理解できない。
長所:これもハッカーが使うらしい。
短所:コンピュータごとに種類が違うらしい。どれが、ノートパソコン向けなのか分からない。
- パイソン
長所:たくさんページがある。
短所:曽根のおすすめなので、これにするとに負けた気がする。
絞り込み
これらのなかからCとLispとジャバとアセンブラを候補とし、さらに調べてみました。
盛りだくさんのCommonLispと最低限のSchemeとが有名。Schemeを使うひとは、Schemerと呼ばれる。かっこいい。
- C
時代遅れで問題が起きやすいが、使いこなせばコンピュータの性能を引き出せる。なんかかっこいい。
- ジャバ
オブジェクト指向というのがCよりもすごく、初心者でも安心。
昔は、これを使うと性能が高かったけど、今は、コンピュータもがんばってるのでそれほどでもない。
結論
どれか一つは選べないので、全部試してみることにしました。インストールの仕方を教えてもらって、SBCLとnasmを入れました。Cとジャバは入ってました。いよいよプログラミングを始めたいと思います。歴史的な登場順に合わせてアセンブラ、Lisp、C、ジャバの順番に学習してみたいと思います。