04.md 3.88 KB
Newer Older
morifuji.koudai's avatar
morifuji.koudai committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
こんにちは。敗北を知った4章です

アセンブリのとこまでやってきたけど心が折れそう

[https://www.oreilly.co.jp/books/9784873117126/:embed:cite]

## 4章 機械語

### 理論

#### アドレッシングモード

要求されたメモリのワードに対してそのアドレスを指定する方法

#### 直接アドレッシング

引数にアドレスを直接渡してアクセスすること

```
LOAD R1, 67
LOAD R1, bar
```

#### イミディエイトアドレッシング

引数の値を直接渡す

```
LOADI R1, 67
```

#### 関節アドレッシング



#### Hack機械語の仕様

#### メモリアドレス空間

- 命令メモリ

CPUは命令メモリを読み込み実行する。リードオンリー

- データメモリ

#### レジスタ

morifuji.koudai's avatar
morifuji.koudai committed
48
D/Aの2種類。
morifuji.koudai's avatar
morifuji.koudai committed
49 50 51 52 53

D=データ値を保存する。

A=データ値とアドレスレジスタと解釈される=値として利用したりアドレスとして利用したりできる

morifuji.koudai's avatar
morifuji.koudai committed
54
M=Aのアドレスが参照している値(仮想の値。**内部でAレジスタが示すアドレスの値を取得するルール**
morifuji.koudai's avatar
morifuji.koudai committed
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

#### 命令

命令は、16bitである。そのうち、先頭の1bitはA/Cの選別に利用する

#### A命令

Aレジスタに15bitの値を設定する命令

```vhdl
@100 // 100Aレジスタに保存

@500 // 500Aレジスタに保存

@R0  // 先頭のレジスタをAレジスタに保存
```

#### C命令

`dest = comp;jamp`で構成された命令。

morifuji.koudai's avatar
morifuji.koudai committed
76 77 78
```
@sum   //A命令
M=D    //C命令
morifuji.koudai's avatar
morifuji.koudai committed
79

morifuji.koudai's avatar
morifuji.koudai committed
80 81 82 83
@index //A命令
D=M    //C命令
D;JEQ  //C命令
```
morifuji.koudai's avatar
morifuji.koudai committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236

#### シンボル

- R0~R15は、 アドレス0~16のレジスタとして使用可能
- `@SCREEN`は、スクリーンの左上のアドレスを示す
- `@KBD`は、キーボードの出力アドレスを示す。値は未入力なら0,入力しているなら入力値である

#### 変数シンボル

ユーザーが定義できるシンボル。アドレスは16から始まる

```vhdl
@sum  // A=16である
M=1   // アドレス161が設定されている

```

## 実装

まずは掛け算 を実装。

加算減算しかできないので、愚直に実装

```vhdl
@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:



```vhdl
// 初期化
// 最大スクリーンアドレスの計算
@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 //D0かどうか

@LOOP
D;JNE

@KEY
0;JMP
(END)

```



👇この部分で2時間ほどつまった。

`@address`には現在のアドレスを入れているが、`A=A+1`とすると同時に`@address`も一つずれると思い込んでいた(実際は、`@address`は元のアドレスのまま。動かない。値が動くだけ)

```vhdl
@address
A=M // 値のアドレスに移動
M=D //アドレスの値をcolor

D=A+1 //アドレスに1加えたところに移動
@address // 必要!!!
M=D // 次に移動するために新たなアドレスを値として保存


```