尝试此操作后,我的代码将无法工作。有人能告诉我它是怎么做的吗?
说明-
如果愿意,请关闭此程序的分支和加载延迟。这将使它变得简单得多。请确保打开内存映射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指令。