ARMの逆アセンブルを読んでいると、「tst r0,r2,LSL r1」のような命令が出てきて混乱する人は多いです。
特に「r2 を r1 ビット左シフト(LSL)」という表現は、初心者にはかなり分かりづらく感じます。
この記事では、ARM命令の基本から、「tst」「LSL」「beq」の意味を、実際のレジスタ値を使ってわかりやすく解説します。
まず命令全体を分解してみる
今回のコードは次の2行です。
tst r0,r2,LSL r1 beq 0xAAAAAA
これは大きく分けると、次のような流れです。
- r2をr1ビット左にずらす
- その値とr0をAND演算する
- 結果が0ならbeqで分岐する
つまり、「特定ビットが立っているかチェックする命令」に近い使い方です。
LSLとは何か
LSLは「Logical Shift Left」の略で、日本語では「論理左シフト」と呼ばれます。
簡単に言うと、ビット列を左へずらす処理です。
例えば、次のようになります。
| 元の値 | LSL 1後 |
|---|---|
| 0001 | 0010 |
| 0010 | 0100 |
| 0100 | 1000 |
左に1ビットずらすと、値は基本的に2倍になります。
つまり、LSLは「ビットを左へ移動する命令」です。
「r2,LSL r1」の意味
「r2,LSL r1」は、「r2の値を、r1で指定されたビット数だけ左シフトする」という意味です。
例えば、次の値を考えます。
r2 = 0b00000001 r1 = 3
この場合、r2を3ビット左へ移動します。
00000001 → 00001000
つまり結果は8になります。
r1の値が「何ビット動かすか」を決めています。
tst命令とは
tst命令は、「AND演算だけして結果を保存しない命令」です。
実際にはフラグだけ更新します。
つまり次のような処理です。
r0 AND (r2をLSLした値)
結果そのものは保存されません。
代わりに、結果が0かどうかをCPU内部フラグに記録します。
具体例で動きを見る
例えば次の値を設定します。
r0 = 0b00001000 r2 = 0b00000001 r1 = 3
まず、r2を3ビット左へ移動します。
00000001 → 00001000
次にtstがAND演算します。
00001000 AND 00001000 ---------------- 00001000
結果は0ではありません。
そのため、Zeroフラグは立たず、beqはジャンプしません。
beq命令の意味
beqは「Branch if Equal」の略です。
ARMでは、「演算結果が0だったら分岐する」という意味でよく使われます。
つまり今回のコードでは、次の条件になります。
もしAND結果が0なら 0xAAAAAAへジャンプ
逆に、0でなければそのまま次の命令へ進みます。
ジャンプするケースも見てみる
今度は別の値を使います。
r0 = 0b00000100 r2 = 0b00000001 r1 = 3
まずLSL。
00000001 → 00001000
AND演算。
00000100 AND 00001000 ---------------- 00000000
結果が0になりました。
この場合、Zeroフラグが立つため、beqが実行されて0xAAAAAAへ分岐します。
実際には「ビットチェック」に使われる
このようなコードは、実際には特定ビットのON/OFF確認によく使われます。
例えば、フラグ管理やハードウェアレジスタ確認などです。
「指定位置のビットが立っているか?」を高速に判定できます。
ARMでは、このようなビット演算が非常に多く使われます。
まとめ
「tst r0,r2,LSL r1」は、まずr2をr1ビット左へシフトし、その値とr0をAND演算する命令です。
tstは結果を保存せず、「0だったかどうか」だけをCPUフラグへ記録します。
その後のbeqは、「結果が0だった場合だけジャンプする」という意味になります。
最初は難しく見えますが、「LSLでビット移動 → ANDで比較 → 0なら分岐」という順番で考えると理解しやすくなります。


コメント