我正在尝试用MIPS编写程序,该程序使用轮询从键盘读取字符,然后使用内置的键盘和显示MMIO模拟器显示它。不幸的是,我无法理解所使用的寄存器和控制位背后的概念,但一直试图从在线示例中找出它。
这是我到目前为止所写的内容:
.data
.text
.globl main
main:
.eqv RCR 0xffff0000 # Receiver Control Register (Ready Bit)
.eqv RDR 0xffff0004 # Receiver Data Register (Key Pressed - ASCII)
.eqv TCR 0xffff0008 # Transmitter Control Register (Ready Bit)
.eqv TDR 0xffff000c # Transmitter Data Register (Key Displayed- ASCII)
keyWait: lw $t0, RCR
andi $t0, $t0, 1
beq $t0, $zero, keyWait
lb $a0, RDR
我认为这里发生的是keyWait
继续循环,直到就绪位设置为1(*),然后密钥的ASCII值存储在$a0
中。这是对的吗?
如果这是正确的,我如何使用与TCR和TDR相同的轮询技术在显示器上打印字符?
*我不明白为什么需要使用andi
操作进行检查 - 如果$t0
为1(或0),则and
为1 ,等于1(或0),然后存储在$t0
?那么$t0
的值是否与此操作之前保持不变?
修改
这是我尝试将按键数据传递给显示器。
.data
.text
.globl main
main:
.eqv RCR 0xffff0000 # Receiver Control Register (Ready Bit)
.eqv RDR 0xffff0004 # Receiver Data Register (Key Pressed - ASCII)
.eqv TCR 0xffff0008 # Transmitter Control Register (Ready Bit)
.eqv TDR 0xffff000c # Transmitter Data Register (Key Displayed- ASCII)
keyWait: lw $t0, RCR
andi $t0, $t0, 1
beq $t0, $zero, keyWait
lbu $a0, RDR
displayWait: lw $t1, TCR
andi $t1, $t1, 1
beq $t1, $zero, displayWait
sb $a1, TDR
li $v0, 11
syscall
j keyWait
这只是一个测试程序,它应该在MMIO显示模拟器上打印字符,也可以在MIPS中的控制台中打印。它正在做后者,但不在显示模拟器上。在显示模拟器中,每次按下一个键时Cursor:
都会递增,但不会打印任何内容。我错过了什么?
答案 0 :(得分:1)
您可能没有点击"连接到MIPS"。
请参阅此答案:How to print to the screen from MIPS assembly
当我测试时,我发现如果你停止模拟,重新加载你的程序,你可能必须点击"断开与MIPS的连接"然后"连接到MIPS"再次(即切换一下)
另外,错误:来自RDR
的数据位于$a0
,但您要存储到TDR
的{{1}}
在链接中,请注意样式与您的略有不同。在链接中,它们使用基址寄存器的偏移而不是硬连接地址。对于[在现实世界中的设备驱动程序]中的设备来说,这是更常见的,特别是如果可以配置/更改设备的基地址。
此外,在$a1
中,如果查看硬连线与基本寄存器版本中伪操作产生的实际低电平指令,基址寄存器版本更紧凑(即注入的{{1} }}))
因此,我重新编写了代码以使用基址寄存器:
mars
我做了一点"花哨的步法"上面有lui
。在一般情况下,尽管它有点冗长,但可能更清楚:
.data
.eqv MMIOBASE 0xffff0000
# Receiver Control Register (Ready Bit)
.eqv RCR_ 0x0000
.eqv RCR RCR_($s0)
# Receiver Data Register (Key Pressed - ASCII)
.eqv RDR_ 0x0004
.eqv RDR RDR_($s0)
# Transmitter Control Register (Ready Bit)
.eqv TCR_ 0x0008
.eqv TCR TCR_($s0)
# Transmitter Data Register (Key Displayed- ASCII)
.eqv TDR_ 0x000c
.eqv TDR TDR_($s0)
.text
.globl main
main:
li $s0,MMIOBASE # get base address of MMIO area
keyWait:
lw $t0,RCR # get control reg
andi $t0,$t0,1 # isolate ready bit
beq $t0,$zero,keyWait # is key available? if no, loop
lbu $a0,RDR # get key value
displayWait:
lw $t1,TCR # get control reg
andi $t1,$t1,1 # isolate ready bit
beq $t1,$zero,displayWait # is display ready? if no, loop
sb $a0,TDR # send key to display
li $v0,11
syscall
j keyWait