背景:ぱっと見ただけだと、TTLかOPアンプにしか見えないSTM32C0*1に興味が湧いて、アセンブラやコンパイラを使わず手でプログラムすることにした。
やりたいこと:GDB+OpenOCDで機械語を手で書き込み実行する。flashにもツールを使わず手で書き込む。最終的には俺FORTHを導入したい
詳細:
まずはハンドアセンブルでADD命令を走らせてみる
RAM領域をダンプ
(gdb) x/8xh 0x20000000 0x20000000: 0x4879 0x68c1 0x2900 0xd503 0x4978 0x6001 0x4978 0x6001
0x2000_0000番地に ADD命令(Rd += U8)を書く。0x3001の場合、R0 += 1
(gdb) set {short}0x20000000 = 0x3001 (gdb) x/4xh 0x20000000 0x20000000: 0x3001 0x68c1 0x2900 0xd503
細かい指定していないけど、ARMに対応して機械語の逆アセンブルもできている(なぜだろうか? RaspberryPiがArmだから?)
(gdb) x/4i $pc => 0x20000000: adds r0, #1 0x20000002: ldr r1, [r0, #12] 0x20000004: cmp r1, #0 0x20000006: bpl.n 0x20000010
元からのプログラムが add r0,#1というオチは?(そんな偶然はないか)
STM32C0(Cortex-M0)のレジスタを表示
(gdb) i r r0 0x10000000 268435456 r1 0xe5e5e5e5 -437918235 r2 0x80c8 32968 r3 0x66000000 1711276032 r4 0x20000360 536871776 r5 0x40005400 1073763328 r6 0xffffffff -1 r7 0xffffffff -1 r8 0xffffffff -1 r9 0xffffffff -1 r10 0xffffffff -1 r11 0xffffffff -1 r12 0xffffffff -1 sp 0x20000d80 0x20000d80 lr 0x1fff0cc1 536808641 pc 0x1fff0cce 0x1fff0cce xpsr 0x1000000 16777216 msp 0x20000d80 0x20000d80 psp 0xfffffffc 0xfffffffc primask 0x1 1 basepri 0x0 0 faultmask 0x0 0 control 0x0 0
r0 の値は、 0x1000_0000
PCを0x2000_0000に変更
(gdb) set $pc=0x20000000 (gdb) print $pc $1 = (void (*)()) 0x20000000
機械語で1語分実行
(gdb) ni 0x20000002 in ?? ()
レジスタ R0を表示
(gdb) print/x $r0 $3 = 0x10000001
1増えている。意図通りにR0 += 1となった。
機械語を数語走らせるには手で打ち込んでもいいのだけど、(幸いにも)段々とコードが増えるとやってられない。GDBではコマンド操作をスクリプト化できるので、正常動作を確認してFIXできた分はスクリプトによる打ち込みに置き換える。