SNSへはこちら

ARMマイコンのバイナリを手打ちする(on STM32) (2)

モチベ

前回の記事では LED を付けるだけのことをやって自室で一人興奮していたのですが(記事投稿日は今日ですが実際に出来たのは昨日)、今日になってLチカしなきゃつまんなくねと思ったのでやってみようと思いました。これが地獄の始まりだった...

ハンドアセンブル地獄

前回は全て 16bit 命令でやっていたのですが、いまいちパッとしないので 32bit 命令を混在させてやってみました。これも地獄への手引きでした。一応出来ましたが、未だわからないことが...とりあえず分かったことを挙げます。僕自身 CPU 初心者なのであれですがね...

  • 32bit オペコードはハーフワードごとにリトルエンディアン。
    • 例えば 00 1F 3A D0 だったら 1F 00 D0 3A となる。
    • 32bit のデータは全て逆順になる。
  • 分岐命令のジャンプ先アドレス指定が謎。アドレス値のシフトやプログラムカウンタの理解は十分なはずだが...

ということで4時間ずっとやってました。もう絶対にやらない。アセンブラのない昔の人の気持ちがよくわかりました。いい経験でしたね。でももうやらない

このままコマンドを載せるだけでもアレなので、デバッグの時に使ったコマンドをご紹介します。

逆アセンブル

objdump で出来るんですが、 -D オプションを付けても「ファイルフォーマット知らんぞ」と怒られます。さらにアーキテクチャを指定しなければなりません。
以下のコマンドで出来ます。というか非常に役に立ちました。

$ arm-none-eabi-objdump -b binary -m arm  -M force-thumb -D ~/testt.bin | less

-M force-thumb は全てのデータを強制的に Thumb モードコードとして解釈させるオプションです。

コード

以下にどうぞ。長いですよね。

$ echo 00 30 00 20 09 00 00 08 17 48 40 F2 00 01 C0 F2 40 01 01 60 15 48 40 F2 01 01 01 60 40 F2 F4 12 00 F0 06 F8 12 48 01 68 81 F0 01 01 01 60 F5 E7 10 48 40 F2 E8 31 01 60 0F 48 00 21 01 60 0F 48 01 21 01 60 00 2A 0A D0 03 68 40 F2 00 01 C0 F2 01 01 0B 40 00 2B F7 D0 A2 F2 01 02 F2 E7 01 68 81 F0 01 01 01 60 70 47 14 10 02 40 00 14 00 48 14 14 00 48 14 E0 00 E0 18 E0 00 E0 10 E0 00 E0 | xxd -r -p >~/testt.bin

動作

動画を上げておきます。このたった10秒の為に4時間頑張ったと思うと虚無感がすごいですよね(もちろん同時に達成感もある)。

ちなみにハンドアセンブルしていた紙の画像も参考程度に上げておきます。字が汚いですが勘弁してください。。。クリックで別タブにてフルサイズをご覧になれます。

参考までに

上で作った testt.binobjdump した結果を載せます。最初の方と最後の方は謎の命令として解釈されていますが、そうではなくただの 32bit 定数値であることにご注意ください。


/Users/yuki/testt.bin: file format binary Disassembly of section .data: 00000000 <.data>: 0: 3000 adds r0, #0 2: 2000 movs r0, #0 4: 0009 movs r1, r1 6: 0800 lsrs r0, r0, #32 8: 4817 ldr r0, [pc, #92] ; (0x68) a: f240 0100 movw r1, #0 e: f2c0 0140 movt r1, #64 ; 0x40 12: 6001 str r1, [r0, #0] 14: 4815 ldr r0, [pc, #84] ; (0x6c) 16: f240 0101 movw r1, #1 1a: 6001 str r1, [r0, #0] 1c: f240 12f4 movw r2, #500 ; 0x1f4 20: f000 f806 bl 0x30 24: 4812 ldr r0, [pc, #72] ; (0x70) 26: 6801 ldr r1, [r0, #0] 28: f081 0101 eor.w r1, r1, #1 2c: 6001 str r1, [r0, #0] 2e: e7f5 b.n 0x1c 30: 4810 ldr r0, [pc, #64] ; (0x74) 32: f240 31e8 movw r1, #1000 ; 0x3e8 36: 6001 str r1, [r0, #0] 38: 480f ldr r0, [pc, #60] ; (0x78) 3a: 2100 movs r1, #0 3c: 6001 str r1, [r0, #0] 3e: 480f ldr r0, [pc, #60] ; (0x7c) 40: 2101 movs r1, #1 42: 6001 str r1, [r0, #0] 44: 2a00 cmp r2, #0 46: d00a beq.n 0x5e 48: 6803 ldr r3, [r0, #0] 4a: f240 0100 movw r1, #0 4e: f2c0 0101 movt r1, #1 52: 400b ands r3, r1 54: 2b00 cmp r3, #0 56: d0f7 beq.n 0x48 58: f2a2 0201 subw r2, r2, #1 5c: e7f2 b.n 0x44 5e: 6801 ldr r1, [r0, #0] 60: f081 0101 eor.w r1, r1, #1 64: 6001 str r1, [r0, #0] 66: 4770 bx lr 68: 1014 asrs r4, r2, #32 6a: 4002 ands r2, r0 6c: 1400 asrs r0, r0, #16 6e: 4800 ldr r0, [pc, #0] ; (0x70) 70: 1414 asrs r4, r2, #16 72: 4800 ldr r0, [pc, #0] ; (0x74) 74: e014 b.n 0xa0 76: e000 b.n 0x7a 78: e018 b.n 0xac 7a: e000 b.n 0x7e 7c: e010 b.n 0xa0 7e: e000 b.n 0x82

  • もう二度とやらない
  • そういえば IT ブロックとか使えばよかったね。今更ながら。
    • mov でなく movs にも出来た箇所がある。反省。
    • 反省とか言っているが本当にもう二度とやらないからね!