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

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 address
	add $t3,$0, 0xbf000418 #display char address
	add $s2, $s2, 0x3ffffff #delay time
	add $s0, $0,0x55 #LED: "# # # # " 
update:
	sw $s0,0($t0) #send to LED
	sw $s0,0($t3) #send to display
	sw $s0,8($t3) #send to display
	sw $s0,16($t3) #send to display
	sw $s0,24($t3) #send to display
	sw $s0,32($t3) #send to display
	sw $s0,40($t3) #send to display
	sw $s0,48($t3) #send to display
	sw $s0,56($t3) #send to display

	add $t1, $0, 0

delay:
	add $t1, $t1, 1
	bne $t1, $s2, delay

	add $s0, $s0, 1
	b 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,现在很便宜了,进出都是按秒算的。。。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值