轮询 I/O (MIPS)
Polling I/O (MIPS)
我正在尝试在 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
ed with 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:
都会递增,但不会打印任何内容。我错过了什么?
您可能没有点击 "Connect to MIPS"。
看到这个答案:How to print to the screen from MIPS assembly
当我测试时,我发现如果你停止模拟,重新加载你的程序,你可能必须点击 "Disconnect from MIPS",然后再次点击 "Connect to MIPS"(即稍微切换一下)
还有一个 bug:来自 RDR
的数据在 $a0
中,但你正在从 [=15] 存储到 TDR
=]
从 link 中,请注意 样式 与您的略有不同。在 link 中,他们使用基址寄存器的偏移量而不是硬连接地址。这对于设备 [在现实世界中的设备驱动程序中] 更为常见,特别是如果设备的基地址可以是 configured/changed.
此外,在 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
我对上面的.eqv
做了一点"fancy footwork"。在一般情况下,即使它有点冗长,但这样做可能更清楚:
.eqv RCR 0x0000
lw $t0,RCR($s0) # get control reg
我正在尝试在 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
ed with 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:
都会递增,但不会打印任何内容。我错过了什么?
您可能没有点击 "Connect to MIPS"。
看到这个答案:How to print to the screen from MIPS assembly
当我测试时,我发现如果你停止模拟,重新加载你的程序,你可能必须点击 "Disconnect from MIPS",然后再次点击 "Connect to MIPS"(即稍微切换一下)
还有一个 bug:来自 RDR
的数据在 $a0
中,但你正在从 [=15] 存储到 TDR
=]
从 link 中,请注意 样式 与您的略有不同。在 link 中,他们使用基址寄存器的偏移量而不是硬连接地址。这对于设备 [在现实世界中的设备驱动程序中] 更为常见,特别是如果设备的基地址可以是 configured/changed.
此外,在 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
我对上面的.eqv
做了一点"fancy footwork"。在一般情况下,即使它有点冗长,但这样做可能更清楚:
.eqv RCR 0x0000
lw $t0,RCR($s0) # get control reg