MIPS编码汇编语言-中断



尝试此操作后,我的代码将无法工作。有人能告诉我它是怎么做的吗?

说明-

如果愿意,请关闭此程序的分支和加载延迟。这将使它变得简单得多。请确保打开内存映射I/O。在开始设计或编程之前,请确保您完全了解我网站上的内存映射I/O示例程序的功能。您不会进行轮询,但需要清楚地了解内存映射I/O。

您可能不会对输入或输出使用syscall,因为程序会阻塞输入。相反,使用中断驱动的I/O例程来处理所有输入和输出。您必须通过中断驱动的内存映射输入/输出服务进行所有输入和输出,而不是通过系统调用。您可以不轮询I/O。此程序唯一可以使用的系统调用是一个代码为10的系统调用,用于结束程序。

编写一个程序,该程序以两个相等长度(至少60个字符(的字符数组(用于保存.asciiz字符串(开始,标记为"源"one_answers"显示"。最初,使源数组包含一个在终止NUL之前带有"\n"的字符串。在字符串中包括大小写字母和其他字符(标点符号、数字和空格(。通过将源阵列复制到显示阵列中来启动程序。使用子例程来执行此操作,传入堆栈上两个数组的地址。使用";"真实世界";子程序调用约定。

复制字符串后,启用中断,然后循环,检查变量(可能会被中断处理程序中的代码更改(,直到用户告诉程序退出。每当输出就绪(发送器(中断发生时,中断处理程序都会打印显示数组中的下一个单个字符,在打印"\n"后将其折回开头。每当输入中断(接收器(中断发生时,您将提取用户的输入(一个字符(,并根据用户的输入执行以下任务之一:

's':使用任何简单的排序例程对显示数组进行排序(气泡或波纹也可以(。不要对"\n"进行排序。

"t":切换每个字母字符的大小写(例如,"t"变成"t","t"变成"t",所有非字母字符保持不变(。

"a":再次用源元素替换显示数组元素。

"r":反转显示数组中的元素(再次,不包括"\n"(。

'q':退出--终止程序执行。

忽略输入中的任何其他字符。在中断处理程序中处理来自用户的命令,而不是在主程序中。

"q"命令应该只设置主程序(重复(查询的变量,这将导致主程序退出,并返回代码为10的系统调用。您不能使用寄存器在程序和中断处理程序之间发送信息。

注意:在显示数组的中间可能会发生中断,因此显示的字符可能会更改中间行。这个程序显然是在以前的赋值基础上设计的,所以您应该尽可能重用代码。主要的新功能是中断驱动的输入和输出。您将在每个字符到达时读取并处理每个字符,而不是在一个系统调用中读取整个字符串。同样,您可能不会对任何I/O使用syscall。这总共大约是三四页代码。

这是我的代码,但我无法让它工作-

prompt: .asciiz "SPIM IO Test.nOnly runs with -mapped_io flag.nPlease type 6 input lines:n"
nl:      .asciiz "n"
.text
.globl main
main:
li $v0 4
la $a0 prompt
syscall
# Register usage:
#            s0            loop counter
#            t0            address of recv_ctrl
#            t1            address of recv_buffer
#            t2            address of trans_ctrl
#            t3            address of trans_buffer
#            t4, t5            temporaries
#            t6            char read from input
#            t7            1 => char in t6
li      $s0, 3            # loop counter
li       $t0, 0xffff0000      # recv ctrl
li      $t1, 0xffff0004      # recv buf
li       $t2, 0xffff0008      # trans ctrl
li       $t3, 0xffff000c      # trans buf
# First, read and echo 3 lines of input by polling the IO registers, not through
# interrupts:
mtc0      $0, $12            # Clear IE bit in Status reg to disable interrupts
l1:
lw      $t4, 0($t0)      # Wait for receiver ready
and       $t4, $t4, 1
beq      $t4, 0, l1
lw      $t6, 0($t1)      # Read character
l2:
lw      $t4, 0($t2)      # Wait for transmitter ready
and      $t4, $t4, 1
beq      $t4, 0, l2
sw      $t6, 0($t3)      # Write character
beq      $t6, 0xa, decr      # New line (nl)
bne      $t6, 0xd, l1      # Carriage return (cr)
decr:
add      $s0, $s0, -1      # Decrement line counter
bne     $s0, 0, l1      # If not zero, get another line
# Second, read and echo 3 lines of input by through interrupts:
mfc0      $t4, $13
and      $t4, 0xffff00ff      # Clear IP bits in Cause register
mtc0      $t4, $13
li      $s0, 3            # loop counter
li      $t4, 0x2      # Enable device interrupts
sw      $t4, 0($t0)
sw      $t4, 0($t2)
mfc0      $t4, $12      # Enable interrupts and mask in Status reg
ori      $t4, $t4, 0xff01
mtc0      $t4, $12
l3:      b      l3            # Loop waiting for interrupts
# Trap handler. Replaces the standard SPIM handler.
.ktext 0x80000180
mfc0      $t4, $13      # Get ExcCode field from Cause reg
srl      $t5, $t4, 2
and      $t5, $t5, 0x1f      # ExcCode field
bne      $t5, 0, exception
# An interrupt:
and      $t5, $t4, 0x800      # Check for IP3 (HW 1)
beq      $t5, 0, check_trans
# Receiver interrupt:
lw      $t5, 0($t0)      # Check receiver ready
and      $t5, $t5, 1
beq      $t5, 0, no_recv_ready      # Error if receiver is not ready
lw      $t6, 0($t1)      # Read character
li      $t7, 1
beq      $t6, 0xa, decr2      # New line (nl)
bne      $t6, 0xd, next      # Carriage return (cr)
decr2:
add      $s0, $s0, -1      # Decrement line counter
next:
mfc0      $t4, $13      # Get Cause register
and      $t4, 0xfffff7ff      # Clear IP3 bit
mtc0      $t4, $13
check_trans:
beq      $t7, 0, ret_handler      # No char to write yet
and      $t5, $t4, 0x400      # Check for IP2 (HW 0)
beq      $t5, 0, check_loop
# Transmitter interrupt:
lw      $t5, 0($t2)      # Check transmitter ready
and      $t5, $t5, 1
beq      $t5, 0, no_trans_ready
sw      $t6, 0($t3)      # Write character
li      $t7, 0
mfc0      $t4, $13      # Get Cause register
and      $t4, 0xfffffbff      # Clear IP2 bit
mtc0      $t4, $13
check_loop:
bne      $s0, 0, ret_handler      # If line counter not zero, get another line
# Done echoing, so terminate program.
li      $v0, 10
syscall                  # syscall 10 (exit)
# Return from handler.
ret_handler:
mfc0      $t4, $12      # Enable interrupts and mask in Status reg
ori      $t4, $t4, 0xff01
mtc0      $t4, $12
eret                  # return to interrupted instruction
exception:
li      $v0, 4            # Non-interrupt exception
la      $a0, other_str      # Print message and ignore
syscall
b      ret_handler
no_recv_ready:
li      $v0, 4            # Receiver was not ready after interrupt
la      $a0, no_recv_str      # Print message and ignore
syscall
b      ret_handler
bad_int:
li      $v0, 4            # Interrupt was not from recv or trans
la      $a0, bad_int_str      # Print message and ignore
syscall
b      ret_handler
no_trans_ready:
li      $v0, 4            # Transmitter was not ready after interrupt
la      $a0, no_trans_str      # Print message and ignore
syscall
b      ret_handler
.data
other_str:
.asciiz "Non-interrupt exceptionn"
no_recv_str:
.asciiz "Receiver not readyn"
no_trans_str:
.asciiz "Transmitter not readyn"
bad_int_str:
.asciiz "Unknown interruptn"

我正在进行一项非常类似的任务,并且是MIPS的新手。仔细看一下这个程序,我认为pgm底部(第123行(内核代码中的指令应该是.kdata,而不是.data。此外,帖子中缺少main上面的.data指令。

最新更新