Skip to content

Commit

Permalink
Add explanation of 4bit rotate.
Browse files Browse the repository at this point in the history
  • Loading branch information
karino2 committed Jan 15, 2019
1 parent 0097e4e commit 8571375
Showing 1 changed file with 119 additions and 3 deletions.
122 changes: 119 additions & 3 deletions arm_asm.md
Original file line number Diff line number Diff line change
Expand Up @@ -2317,15 +2317,131 @@ putchar_nomem.binとかprint_hex.binとかも順番にサポートしていく
最後まで追加が終わったら「ここはあんまりだなぁ」と思う所だけハードコードじゃなく直しておきましょう。
直す時はなるべくまずfailするUnit Testを追加してから直すように。

## 即値をちゃんと表示しよう
## 即値をちゃんと表示しよう(4bitローテート対応)

即値のローテートとかの話。大きめの即値をアセンブルしてバイナリ見て、4bitローテートの説明をする。
movの命令などでは12bitの即値のフィールドを持つ事が出来ます。
この12bitの即値、ARMでは少し特殊な決まりがあります。

12bitの即値は、そのまま数字の値として用いるのではなく、
上位4bitはローテート値として用い、下位の8bitだけが値となります。

これまで見てきたものは、12bit即値のフィールドの値が、0とか64とか小さな値ばかり入れていたので、この上位4bitは0でした。
だから下位8bitの値がそのまま使われるので、4bitローテートの仕組みを知らなくても問題なかったのです。

ですが、この上位4bitが0じゃない時は、この4bitの部分は特別な解釈を必要とします。
その解釈方法を以下に述べます。

### 下位8ビットの解釈

まず、下位8bitを32bitの数値としてゼロ拡張します。つまり上に0を24個つける、という事です。

### 上位4ビットの解釈

上位4bitをunsignedな数値として解釈し、この「unsignedな数値の値*2」だけ、先ほどのゼロ拡張した値を右にシフトします。

4bitというのは0から15までの値が表せます。これを2倍にすると、0から30までの、偶数をすべて表す事が出来ます。
つまり0, 2, 4, 6, 8, ... , 28, 30

ですね。

### 具体例その1、0xff000000

以下の解説は[ARM immediate value encoding](https://alisdair.mcdiarmid.org/arm-immediate-value-encoding/)の最後のボタンをポチポチしながら読むと良いです。

例えば、下位8bitの値を右に8シフトすると、32ビットのうち上位8ビットを占める事になります。

8シフトする、というのは、4bitを二倍して作るとすると4bitの値は4、つまり

```
0100
```

となります。

だから、例えば下位8bitが 1111 1111だった場合、つまり12ビット全体では

```
0100 1111 1111
```

だった場合、これを解釈すると、「1111 1111を32bitゼロ拡張して 0100*2だけ右シフトする」という意味になり、

```
0x000000ff >> 8
```

と同じ意味、つまり

```
0xff000000
```

となります。

つまり、以下の12ビット即値は

```
0100 1111 1111
```

以下の32ビットの値を表す事になります。

```
1111 1111 0000 0000 0000 0000 0000 0000
```

12bitなのに大きな負の値が表せるんですね。

もちろんシフトなので、32bitの全数字が表せる訳ではありません。飛び飛びの値になります。
ただ、下位8bitは連続した整数を表しているので、0から255までは飛びが無く全部表せます。

12bit即値は慣れれば解読は容易ですが、どの数字が12 bit即値で表せるか、という逆方向の変換は、少なくとも自分は出来ません。(低レベル強い人は出来るんでしょうが)。

### 具体例その2、0x08000000

他の例も見てみましょう。
アセンブリの解説の所で、メモリを使ってスタックにレジスタの値を保存する例を見ました。

この時、スタックの開始アドレスとしては0x08000000としたのを覚えていますか?
この値も4bitローテートのおかげで12bit即値で表す事が出来ます。

0x8は2bitでは1000なので、目標とするのは、

```
0000 1000 0000 0000 0000 0000 0000 0000
```

という32bitの値となります。
これは0010を右に、、、6?シフトすれば良さそう。

という事は4bitローテートの値は3となります。
3という事は0011ですね。

下位8bitは0010、つまり0000 0010です。
この二つを合わせると

```
0011 0000 0010
```

となります。これが0x08000000になります。

### 課題: 以下を解読してみよう

以下の命令を解読してみましょう。

```
02 D9 A0 E3
```

が確かr13に0x80000入れる奴だった気がするのでこれの話をする。
ヒントとしてはmov命令です。

### 参考サイト

正確な仕様は[データシート](https://developer.arm.com/docs/ddi0027/latest/arm7di-data-sheet)のp34, 4.4.3のImmediate operand rotatesに書いてあります。

また、先ほども紹介しましたが、英語で良ければ、以下のサイトの解説が詳しい。[ARM immediate value encoding](https://alisdair.mcdiarmid.org/arm-immediate-value-encoding/)
このサイトの最後に実際に数値を入力してみる事が出来るフォームがついていて、対話的に試せるので英語を読む気が無い人も、このフォームは是非使ってみてください。


# 05 簡易アセンブラを作ろう
Expand Down

0 comments on commit 8571375

Please sign in to comment.