利用qemu写mips汇编程序控制malta显示器

来源:互联网 发布:淘宝客服投诉电话400 编辑:程序博客网 时间:2024/06/09 02:56
hello world不会写,先玩玩malta虚拟器上的跑马灯,就是qemu起来后ctrl+atl+5切换出来那个,安装debian mips版本后会有个"LINUX ON MALTA"在那一直循环。

参考之前的文章,windows和linux下都有qemu,gnu的交叉编译工具也都有,所以两个平台应该都能跑。

本文参考了:
http://comments.gmane.org/gmane.comp.emulators.qemu/107966
http://comments.gmane.org/gmane.comp.emulators.qemu/11911
还有qemu对malta机器模拟的源码:
http://svn.peeklinux.com/trunk/qemu/hw/mips_malta.c 这个东西很重要,能看到很多内部实现。

注意:
1. qemu-system-mipsel的-bios参数没实现,指定什么参数启动的时候都不会加载。
2. qemu-system-mipsel的-kernel参数必须指定elf文件,经过objdump -O binary的文件时不会被加载的,看过那篇文章玩qemu-system-arm的人可能会想不通(http://balau82.wordpress.com/2010/02/14/simplest-bare-metal-program-for-arm/)。
3. qemu-system-mipsel的kernel加载位置就是ld时指定链接模板定义的,建议为0x80100000, 这是debian linux kernel文件抄来的,应该不会错多少。malta的bios会根据你的elf入口决定跳转位置,但是,你的elf在256M内存之外,它还是会老老实实跳过去。。。
4. 从malta源码看,这个灯的地址应该是0x1fxxxxxx的,但是用调试工具访问这个地址失败。在qemu的monitor console里面x,xp可以看出来,这个地址是物理地址。那么它的映射地址是多少呢?See MIPS RUN这书2.8图2-1有mips系统内存映射。原来是0xbfxxxxx。
5. 不要以为后面就好办了,gdb里面直接设置0xbf000418(显示字符串的起始位置)这个内存值,但是不会生效,在debian里面试过,不行。搜索"LINUX ON MALTA", 原来内核里面定时刷新的。
6. 好吧,qemu-system-mipsel -s -S -kernel xxxx, 然后用gdb target remote :1234进去,这个地址写进去值,没响应。读就不要想了,从源码看这个地址不支持读。这个不知道算不算qemu的bug, 写应该支持啊。
7. 好吧,写个汇编,让程序去说话,终于成功了~~

test.S
Asm代码 复制代码 收藏代码
  1. .global __start   
  2. .text   
  3. __start:   
  4.     add $t0,$00xbf000408 #LED address   
  5.     add $t3,$00xbf000418 #display char address   
  6.     add $s2, $s2, 0x3ffffff #delay time   
  7.     add $s0, $0,0x55 #LED: "# # # # "    
  8. update:   
  9.     sw $s0,0($t0) #send to LED   
  10.     sw $s0,0($t3) #send to display   
  11.     sw $s0,8($t3) #send to display   
  12.     sw $s0,16($t3) #send to display   
  13.     sw $s0,24($t3) #send to display   
  14.     sw $s0,32($t3) #send to display   
  15.     sw $s0,40($t3) #send to display   
  16.     sw $s0,48($t3) #send to display   
  17.     sw $s0,56($t3) #send to display   
  18.   
  19.     add $t1, $00  
  20.   
  21. delay:   
  22.     add $t1, $t1, 1  
  23.     bne $t1, $s2, delay   
  24.   
  25.     add $s0, $s0, 1  
  26.     b update  
.global __start.text__start:add $t0,$0, 0xbf000408 #LED addressadd $t3,$0, 0xbf000418 #display char addressadd $s2, $s2, 0x3ffffff #delay timeadd $s0, $0,0x55 #LED: "# # # # " update:sw $s0,0($t0) #send to LEDsw $s0,0($t3) #send to displaysw $s0,8($t3) #send to displaysw $s0,16($t3) #send to displaysw $s0,24($t3) #send to displaysw $s0,32($t3) #send to displaysw $s0,40($t3) #send to displaysw $s0,48($t3) #send to displaysw $s0,56($t3) #send to displayadd $t1, $0, 0delay:add $t1, $t1, 1bne $t1, $s2, delayadd $s0, $s0, 1b update


test.ld
引用
ENTRY(__start)
SECTIONS
{
    . = 0x80100000;
    .text : { *(.text) }
    .data : { *(.data) }
    .bss : { *(.bss) }
    . = . + 0x1000; /* 4kB of stack memory */
    stack_top = .;
}


Makefile:
引用
all: test
test: testclean
mipsel-linux-gnu-gcc -mips32 -EL -c test.S -o test.o
mipsel-linux-gnu-ld -mips32 -EL -T test.ld test.o -o test
mipsel-linux-gnu-objcopy -O binary test test.bin
testclean:
rm -f test
rm -f test.bin
testrun:
        qemu-system-mipsel  -kernel test


qemu通过ctrl+alt+5切换到led界面,Malta LEDBAR:显示很多跳动的# ###, Malta ASCII跳动显示的是当前字符,实际上LED是字符的二进制格式。

单步汇编调试:
qemu-system-mipsel  -kernel test -s -S
mipsel-linux-gnu-gdb test
(gdb) target remote :1234
(gdb) load
(gdb) break __start ////$pc最开始bios,即0xbfc0.0000
(gdb) i reg
(gdb) c
(gdb) x/16i $pc
(gdb) si

刚学mips, 用C写一样的。玩虚拟机一定要用SSD,现在很便宜了,进出都是按秒算的。。。
原创粉丝点击