こんにちは。敗北を知った4章です
アセンブリのとこまでやってきたけど心が折れそう
[https://www.oreilly.co.jp/books/9784873117126/:embed:cite]
vol.4 いまここ
4章 機械語
理論
アドレッシングモード
要求されたメモリのワードに対してそのアドレスを指定する方法
直接アドレッシング
引数にアドレスを直接渡してアクセスすること
LOAD R1, 67
LOAD R1, bar
イミディエイトアドレッシング
引数の値を直接渡す
LOADI R1, 67
関節アドレッシング
Hack機械語の仕様
メモリアドレス空間
- 命令メモリ
CPUは命令メモリを読み込み実行する。リードオンリー
- データメモリ
レジスタ
D/Aの2種類。
D=データ値を保存する。
A=データ値とアドレスレジスタと解釈される=値として利用したりアドレスとして利用したりできる
M=Aのアドレスが参照している値(仮想の値。内部でAレジスタが示すアドレスの値を取得するルール)
命令
命令は、16bitである。そのうち、先頭の1bitはA/Cの選別に利用する
A命令
Aレジスタに15bitの値を設定する命令
@100 // 100をAレジスタに保存
@500 // 500をAレジスタに保存
@R0 // 先頭のレジスタをAレジスタに保存
C命令
dest = comp;jamp
で構成された命令。
@sum //A命令
M=D //C命令
@index //A命令
D=M //C命令
D;JEQ //C命令
シンボル
- R0~R15は、 アドレス0~16のレジスタとして使用可能
@SCREEN
は、スクリーンの左上のアドレスを示す@KBD
は、キーボードの出力アドレスを示す。値は未入力なら0,入力しているなら入力値である
変数シンボル
ユーザーが定義できるシンボル。アドレスは16から始まる
@sum // A=16である
M=1 // アドレス16に1が設定されている
実装
まずは掛け算 を実装。
加算減算しかできないので、愚直に実装
@sum
M=0
// 残りカウントをR1で初期化
@R1
D=M
@count
M=D
(LOOP)
// チェック
@count
D=M
@END
D;JEQ
// 合計値計算
@R0
D=M
@sum
M=M+D
// カウントを減らす
@count
M=M-1
// ループ繰り返す
@LOOP
0;JMP
(END)
// R2に記録
@sum
D=M
@R2
M=D
@END
0;JMP
次に、スクリーンの入力に合わせて画面を白黒切り替える実装。くそほど詰まった :innocent:
// 初期化
// 最大スクリーンアドレスの計算
@8192 //256*32
D=A
@SCREEN
D=D+A
@MAXADDRESS //最大スクリーンアドレス
M=D
// 以下、無限ループ
(KEY)
@SCREEN
D=A
@address // スクリーンアドレス初期化
M=D
@KBD //キーボード取得
D=M
// 振り分け
@WHITE
D;JEQ
@BLACK
0;JMP
(WHITE)
@color
M=0
@LOOP
0;JMP
(BLACK)
@color
M=-1
@LOOP
0;JMP
// スクリーン書き換え
(LOOP)
@color
D=M
@address
A=M // 値のアドレスに移動
M=D //アドレスの値をcolorに
D=A+1 //アドレスに1加えたところに移動
@address // 必要!!!
M=D // 次に移動するために新たなアドレスを値として保存
@MAXADDRESS
D=M-D //Dが0かどうか
@LOOP
D;JNE
@KEY
0;JMP
(END)
👇この部分で2時間ほどつまった。
@address
には現在のアドレスを入れているが、A=A+1
とすると同時に@address
も一つずれると思い込んでいた(実際は、@address
は元のアドレスのまま。動かない。値が動くだけ)
@address
A=M // 値のアドレスに移動
M=D //アドレスの値をcolorに
D=A+1 //アドレスに1加えたところに移動
@address // 必要!!!
M=D // 次に移動するために新たなアドレスを値として保存