轮询I / O(MIPS) [英] Polling I/O (MIPS)
问题描述
我正在尝试在MIPS中编写一个程序,该程序使用轮询从键盘读取字符,然后使用内置的键盘和显示MMIO模拟器显示它。不幸的是,我无法理解所使用的寄存器和控制位背后的概念,但一直试图从在线示例中找出它。
I am attempting to write a program in MIPS that uses polling to read a character from the keyboard and then displays it using the builtin Keyboard and Display MMIO Simulator. Unfortunately, I am having trouble grasping the concept behind the registers used and the control bits, but have been trying to figure it out from examples online.
这就是我所拥有的到目前为止写的:
Here is what I have written so far:
.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
中。这是正确的吗?
What I believe is happening here is that keyWait
continues to loop until the ready bit is set to 1 (*), and then the ASCII value of the key is stored in $a0
. Is this correct?
如果这是正确的,那么如何使用与TCR和TDR相同的轮询技术在显示器上打印字符?
If this is correct, how can I then print the character on the display using the same polling technique with the TCR and TDR?
*我不明白为什么需要使用 andi
操作来检查 - 如果 $ t0
是1(或0),它是和
ed with 1,等于1(或0),然后存储在 $ T0
?那么 $ t0
的价值是否保持与此操作之前相同?
*I don't understand why this is needed to be checked with the andi
operation - if $t0
is 1 (or 0), it is and
ed with 1, which equals 1 (or 0), which is then stored in $t0
? So the value of $t0
stays as it was prior to this operation regardless?
EDIT
这是我尝试将按键数据传递给显示器。
Here is my attempt at passing the key pressed data to the display.
.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:
每次按下一个键时都会递增,但没有打印任何内容。我缺少什么?
This is just a test program which should print the character on the MMIO Display Simulator, and also in the console within MIPS. It is doing the latter, but not on the display simulator. In the display simulator, Cursor:
is incrementing each time a key is pressed, but nothing is being printed. What am I missing?
推荐答案
您可能没有点击连接到MIPS。
You probably didn't click "Connect to MIPS".
请参阅此答案:如何打印从MIPS程序集到屏幕
当我测试时,我发现如果你停止模拟,重新加载程序,你可能需要点击断开MIPS然后再连接到MIPS(即稍微切换一下)
When I was testing I've found that if you stop simulation, reload your program, you probably have to click on "Disconnect from MIPS" and then "Connect to MIPS" again (i.e. toggle it a bit)
此外, bug :来自<的数据code> RDR 在 $ a0
中,但您存入 TDR
来自 $ a1
Also, a bug: The data from RDR
is in $a0
, but you are storing into TDR
from $a1
从链接中注意样式略有不同你的。在链接中,它们使用基址寄存器的偏移量而不是硬连线地址。对于[在现实世界中的设备驱动程序]中的设备来说,这更常见,特别是如果可以配置/更改设备的基地址。
From the link, notice that the style is slightly different than yours. In the link, they use offsets from a base register rather than hardwiring the addresses. This is much more usual for devices [in device drivers in the real world], particularly if the base address of the device could be configured/changed.
此外,在 mars
,如果你看看硬连线与基本寄存器版本中伪操作产生的实际低电平指令,基址寄存器版本更紧凑(即注入的数量更少 lui
insts)
Also, in mars
, if you look at the actual low level instructions generated from the pseudo-ops in the hardwired vs. base register versions, the base register version is more compact (i.e. fewer injected lui
insts)
所以,我重新设计了你的代码以使用基址寄存器:
So, I've restyled your code to use a base register:
.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
我用 .eqv $ c做了一些花哨的步法 $ c>以上。在一般情况下,即使它更冗长,也可能更清楚:
I did a little "fancy footwork" with the .eqv
above. In the general case, even though it's a bit more verbose, it may be clearer to do:
.eqv RCR 0x0000
lw $t0,RCR($s0) # get control reg
这篇关于轮询I / O(MIPS)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!