Zynq-Qemu上で動作するARMコードを書いてみた
ZynqLinuxとかToppers/FMPとかに頼らずに、ZynqQemu上でシリアル通信に文字を出力するプログラムを書いてみた。
要は、プログラム開始後すぐにシリアルデバイスを初期化して出力するだけのプログラム。
以下、プログラムの主要部分。
xuartps_initとかxuartps_putcharとかシリアルのデバドラ部分(?)はToppers/FMPのtarget/zynq_gcc/target_serial.cからお借り(コピペ)しました(・・・FMPに頼ってる!?笑)。
最初のインラインアセンブラは必要?
[hello_serial.c]
int main(void) { asm("msr cpsr_cxsf, #(0x13 | 0x40 | 0x80)"); xuartps_init(); xuartps_putchar('C'); while(1){} }
そして、コンパイルからの実行。fmpだと、gccで出力されたELFファイルをqemuの-kernelオプションで読み込ませれば動いたような気がするんだけど、今回はべたのバイナリに変換してからじゃないと動作しなかった。
ビルドオプションはFMPのものを参考にしました。-Nの効能は不明。
>arm-none-eabi-gcc -c -mlittle-endian -mcpu=cortex-a9 -g -Wall -O2 -DBASE_ADDR=0x0 -DCA9_PRIVATE_TIMER -D__TARGET_ARCH_ARM=7 -nostdlib -N hello_serial.c >arm-none-eabi-objcopy -O binary hello_serial.o hello_serial.bin >qemu-system-arm -M xilinx-zynq-a9 -m 1024 -smp 2 -serial null -serial stdio -kernel hello_serial.bin -nographic -monitor telnet::4444,server,nowait
QEMUモニターの機能メモその1
◎メモリダンプ(命令列変換!)
xp/[ダンプ数][形式][サイズ] メモリアドレス
xp:コマンド名
ダンプ数:10とか適当に
形式:x=16進,o,d,u,c, "i=アセンブラ命令"
サイズ:b(8bit),h(16bit),w(32bit),g(64bit)
例:xp/40xb 0x10000 00010000: 0xd3 0xf0 0x2f 0xe3 0x03 0x20 0xa0 0xe3 00010008: 0x03 0x30 0xa0 0xe3 0x03 0x40 0xa0 0xe3 00010010: 0x01 0x3a 0xa0 0xe3 0xff 0xef 0x01 0xe3 00010018: 0x00 0x30 0x4e 0xe3 0x2b 0x10 0xa0 0xe3 00010020: 0x0c 0xe0 0x83 0xe5 0x56 0x00 0xa0 0xe3 例:(qemu) x/10i 0x10000 0x00010000: e32ff0d3 msr CPSR_fsxc, #211 ; 0xd3 0x00010004: e3a02003 mov r2, #3 ; 0x3 0x00010008: e3a03003 mov r3, #3 ; 0x3 0x0001000c: e3a04003 mov r4, #3 ; 0x3 0x00010010: e3a03a01 mov r3, #4096 ; 0x1000 0x00010014: e301efff movw lr, #8191 ; 0x1fff 0x00010018: e34e3000 movt r3, #57344 ; 0xe000 0x0001001c: e3a0102b mov r1, #43 ; 0x2b 0x00010020: e583e00c str lr, [r3, #12] 0x00010024: e3a00056 mov r0, #86 ; 0x56
まさか、ここで逆アセンブラができるとは‼便利ーーー‼‼
◎info roms
(qemu)info roms addr=00000000 size=0x00001c mem=ram name="bootloader" addr=00010000 size=0x0000d4 mem=ram name="/home/XXX/hello_serial/hello_serial.bin"
一つ前の記事のバイナリファイルは、メモリ上ではここに読み込まれていたのか‼‼
-kernelオプションをつけると、qemuがbootloaderを用意してくれるのかな。
さっそく覚えたアセンブラメモリダンプでbootloaderのあたりを見てみると、
(qemu) xp/8i 0 0x00000000: e3a00000 mov r0, #0 ; 0x0 0x00000004: e3a01032 mov r1, #50 ; 0x32 0x00000008: e3811c0d orr r1, r1, #3328 ; 0xd00 0x0000000c: e59f2000 ldr r2, [pc, #0] ; 0x14 0x00000010: e59ff000 ldr pc, [pc, #0] ; 0x18 0x00000014: 00000100 andeq r0, r0, r0, lsl #2 0x00000018: 00010000 andeq r0, r1, r0 0x0000001c: 00000000 andeq r0, r0, r0
◎info一覧
info romsに限らず、info mtree, info qtree, info trace-events, etcetc...重要な情報源になりそう。デバックにもかなり有効と思う。
(qemu) info info balloon -- show balloon information info block -- show the block devices info blockstats -- show block device statistics info capture -- show capture information info chardev -- show the character devices info cpus -- show infos for each CPU info history -- show the command line history info jit -- show dynamic compiler info info kvm -- show KVM information info mice -- show which guest mouse is receiving events info migrate -- show migration status info mtree -- show memory tree info name -- show the current VM name info network -- show the network state info numa -- show NUMA information info pci -- show PCI info info pcmcia -- show guest PCMCIA status info profile -- show profiling information info qdm -- show qdev device model list info qtree -- show device tree info registers -- show the cpu registers info roms -- show roms info snapshots -- show the currently saved VM snapshots info status -- show the current VM status (running|paused) info trace-events -- show available trace-events & their state info usb -- show guest USB devices info usbhost -- show host USB devices info usernet -- show user network stack connection states info uuid -- show the current VM UUID info version -- show the version of QEMU info vnc -- show the vnc server status
◎cpu n
番号nのCPUに切り替える