轮询I / O(MIPS)

时间:2016-10-14 20:58:00

标签: io mips polling

我正在尝试用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:都会递增,但不会打印任何内容。我错过了什么?

1 个答案:

答案 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