You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MIPS汇编测验程序定时器问题:计时时无法输入答案

问题原因分析

你的程序当前逻辑是先启动阻塞式的定时器循环,完全占用CPU执行计时,直到倒计时结束后才会执行用户输入代码。这导致计时的10秒内,程序一直卡在timer_loop和delay_loop中,根本没有机会处理用户输入操作,自然无法作答。

解决方案:将计时与输入检查合并

要实现"计时同时允许输入"的效果,需要把计时逻辑和输入检查逻辑合并到同一个循环中:每经过一小段时间就检查一次是否有用户输入,有输入则立即处理并退出计时;无输入则继续倒计时,直到时间耗尽。

针对MARS模拟器,我们可以使用syscall 3非阻塞检查键盘是否有输入(返回值存于$v0,1表示有输入,0表示无),同时调整计时粒度,避免长时间阻塞。

修改后的完整代码

.data

welcomeMsg: .asciiz "Welcome to the Quiz Game!\nPlease choose a subject to play:\n1. Math\n2. English\n3. History\n4. Soccer Sport\n"

chooseMsg: .asciiz "Enter your choice (1 for Math, 2 for English, 3 for History, 4 for Soccer Sport): "

invalidChoiceMsg: .asciiz "Invalid choice. Please enter a number between 1 and 4.\n"

mathWelcomeMsg: .asciiz "You chose Math! Let's solve some equations.\n"

englishWelcomeMsg: .asciiz "You chose English! Let's work on some exercises.\n"

historyWelcomeMsg: .asciiz "You chose History! Let's dive into the past.\n"

soccerWelcomeMsg: .asciiz "You chose Soccer Sport! Let's test your knowledge of football.\n"

questionMath: .asciiz "What is 5 + 3?\n"

answerMath: .asciiz "8\n"

questionEnglish: .asciiz "Correct the following sentence: 'He go to school every day.'\n"

answerEnglish: .asciiz "He goes to school every day."

questionHistory: .asciiz "In which year did the American Civil War end?\n"

answerHistory: .word 1865

questionSoccer: .asciiz "Who is known as the 'King of Football'?\n"

answerSoccer: .asciiz "Pele\n"

userInputBuffer: .space 100

positiveFeedback: .asciiz "Correct answer! You earned 20 points.\n"

incorrectFeedback: .asciiz "Incorrect answer. The correct answer is "

incorrectFeedbackEnd: .asciiz ".\n"

timeUpMsg: .asciiz "Time's up! Please try again.\n"

.text

.globl main

main:
    li $v0, 4
    la $a0, welcomeMsg
    syscall

    li $v0, 4
    la $a0, chooseMsg
    syscall

    li $v0, 5
    syscall

    move $t0, $v0

    li $t1, 1
    li $t2, 2
    li $t3, 3
    li $t4, 4

    beq $t0, $t1, math_quiz
    beq $t0, $t2, english_quiz
    beq $t0, $t3, history_quiz
    beq $t0, $t4, soccer_quiz

    li $v0, 4
    la $a0, invalidChoiceMsg
    syscall

    j main

math_quiz:
    li $v0, 4
    la $a0, mathWelcomeMsg
    syscall

    li $v0, 4
    la $a0, questionMath
    syscall

    # 启动带输入检查的定时器(10秒),处理字符串输入
    li $a0, 10
    la $a1, userInputBuffer
    li $a2, 100
    jal timer_with_str_input

    # 比较答案
    la $a0, userInputBuffer
    la $a1, answerMath
    jal strcmp

    beq $v0, $zero, correct_answer_math
    j incorrect_answer_math

correct_answer_math:
    li $v0, 4
    la $a0, positiveFeedback
    syscall
    j finish

incorrect_answer_math:
    li $v0, 4
    la $a0, incorrectFeedback
    syscall

    li $v0, 4
    la $a0, answerMath
    syscall

    li $v0, 4
    la $a0, incorrectFeedbackEnd
    syscall
    j finish

english_quiz:
    li $v0, 4
    la $a0, englishWelcomeMsg
    syscall

    li $v0, 4
    la $a0, questionEnglish
    syscall

    # 启动带输入检查的定时器(10秒),处理字符串输入
    li $a0, 10
    la $a1, userInputBuffer
    li $a2, 100
    jal timer_with_str_input

    # 比较答案
    la $a0, userInputBuffer
    la $a1, answerEnglish
    jal strcmp

    beq $v0, $zero, correct_answer_english
    j incorrect_answer_english

correct_answer_english:
    li $v0, 4
    la $a0, positiveFeedback
    syscall
    j finish

incorrect_answer_english:
    li $v0, 4
    la $a0, incorrectFeedback
    syscall

    li $v0, 4
    la $a0, answerEnglish
    syscall

    li $v0, 4
    la $a0, incorrectFeedbackEnd
    syscall
    j finish

history_quiz:
    li $v0, 4
    la $a0, historyWelcomeMsg
    syscall

    li $v0, 4
    la $a0, questionHistory
    syscall

    # 启动带输入检查的定时器(10秒),处理整数输入
    li $a0, 10
    jal timer_with_int_input
    move $t5, $v0 # 存储用户输入的整数

    # 加载正确答案
    lw $t6, answerHistory

    # 比较答案
    bne $t5, $t6, incorrect_answer_history
    j correct_answer_history

correct_answer_history:
    li $v0, 4
    la $a0, positiveFeedback
    syscall
    j finish

incorrect_answer_history:
    li $v0, 4
    la $a0, incorrectFeedback
    syscall

    li $v0, 1
    lw $a0, answerHistory
    syscall

    li $v0, 4
    la $a0, incorrectFeedbackEnd
    syscall
    j finish

soccer_quiz:
    li $v0, 4
    la $a0, soccerWelcomeMsg
    syscall

    li $v0, 4
    la $a0, questionSoccer
    syscall

    # 启动带输入检查的定时器(10秒),处理字符串输入
    li $a0, 10
    la $a1, userInputBuffer
    li $a2, 100
    jal timer_with_str_input

    # 比较答案
    la $a0, userInputBuffer
    la $a1, answerSoccer
    jal strcmp

    beq $v0, $zero, correct_answer_soccer
    j incorrect_answer_soccer

correct_answer_soccer:
    li $v0, 4
    la $a0, positiveFeedback
    syscall
    j finish

incorrect_answer_soccer:
    li $v0, 4
    la $a0, incorrectFeedback
    syscall

    li $v0, 4
    la $a0, answerSoccer
    syscall

    li $v0, 4
    la $a0, incorrectFeedbackEnd
    syscall
    j finish

strcmp:
    # 比较两个空终止字符串,相等返回0,否则返回1
    li $t1, 0

compare_loop:
    lb $t2, 0($a0)
    lb $t3, 0($a1)
    beq $t2, $zero, compare_end
    bne $t2, $t3, compare_fail
    addi $a0, $a0, 1
    addi $a1, $a1, 1
    j compare_loop

compare_fail:
    li $v0, 1
    jr $ra

compare_end:
    li $v0, 0
    jr $ra

# 带字符串输入检查的定时器:$a0=倒计时秒数,$a1=输入缓冲区地址,$a2=缓冲区大小
timer_with_str_input:
    move $t1, $a0       # 存储总秒数
    li $t2, 1000        # 每1ms检查一次输入,调整这个值适配你的环境

timer_str_loop:
    blez $t1, timer_end # 时间到,结束

    # 检查是否有键盘输入
    li $v0, 3
    syscall
    beq $v0, 1, read_str_input # 有输入则读取

    # 1ms延迟
    li $t0, 0
delay_str:
    addi $t0, $t0, 1
    bne $t0, $t2, delay_str

    # 每1000次1ms延迟,总时间减1秒
    subi $t1, $t1, 1
    j timer_str_loop

read_str_input:
    # 读取用户字符串输入
    li $v0, 8
    move $a0, $a1
    move $a1, $a2
    syscall
    jr $ra

# 带整数输入检查的定时器:$a0=倒计时秒数,返回用户输入的整数到$v0
timer_with_int_input:
    move $t1, $a0       # 存储总秒数
    li $t2, 1000        # 每1ms检查一次输入,调整这个值适配你的环境

timer_int_loop:
    blez $t1, timer_end # 时间到,结束

    # 检查是否有键盘输入
    li $v0, 3
    syscall
    beq $v0, 1, read_int_input # 有输入则读取

    # 1ms延迟
    li $t0, 0
delay_int:
    addi $t0, $t0, 1
    bne $t0, $t2, delay_int

    # 每1000次1ms延迟,总时间减1秒
    subi $t1, $t1, 1
    j timer_int_loop

read_int_input:
    # 读取用户整数输入
    li $v0, 5
    syscall
    jr $ra

timer_end:
    li $v0, 4
    la $a0, timeUpMsg
    syscall
    j finish # 跳转到程序结束

finish:
    li $v0, 10 # 退出程序
    syscall

关键修改说明

  1. 替换阻塞式定时器为带输入检查的循环:
    • 新增timer_with_str_input和timer_with_int_input两个函数,分别处理字符串输入和整数输入的计时场景。
    • 使用syscall 3非阻塞检查键盘输入,每1ms检查一次,避免长时间占用CPU。
  2. 调整计时逻辑:将原来的1秒大延迟拆分为1ms的小延迟,累计1000次小延迟后减少1秒倒计时,同时在每次小延迟后检查输入。
  3. 输入触发逻辑:一旦检测到有键盘输入,立即执行对应的输入读取操作(字符串或整数),并返回继续处理答案判断。

内容的提问来源于stack exchange,提问作者Diego Manríquez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:07:03