轮询 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),它是 anded 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