2013-10-01 22 views
0

我的程序应该采用两个整数和一个运算符(除法,乘法,加法,减法)。从那里,它会根据需要计算答案和余数。为什么我的程序尽早切断循环?

之后,它应该提示用户是否想用(y/n)选项进行另一次计算。如果是的话,它会重新循环,如果没有,程序就会退出。出于某种原因,它不允许我为(y/n)提供选项,只是跳过我的输入并直接终止。这是我的代码。 (对不起初学者)

在我进入操作员之前,我也会收到一个“未知错误代码45”(弹出窗口?)。

enter image description here

# SPIM Calculator 
# Computer Organization 

    .data 
prompt:   .asciiz "Welcome to SPIM Calculator 1.0!\n" 
first_prompt: .asciiz "Enter the first number: " 
second_prompt: .asciiz "Enter the second number: " 
operator:  .asciiz "Enter the operation (+, -, *, /), then press enter key: " 
error_message: .asciiz "\n\nArgument is invalid. Try again!\n\n" 
sp:    .asciiz " " 
nl:    .asciiz "\n" 
eq:    .asciiz " = " 
parl:   .asciiz "(" 
parr:   .asciiz ")" 
again_prompt: .asciiz "\nWould you like to do another calculation? (y/n) " 
ended_message: .asciiz "\nCalculations complete." 

    .globl main 
    .text 

main: 
    #initialize 
    li $s0, 10 

    # Prompt welcome 
    li $v0, 4   # print string value 4 
    la $a0, prompt  # loads address from memory 
    syscall 

loop: 

    # display prompt for q.1 
    li $v0, 4   # loads value 4 into register v0 which is op code for print string 
    la $a0, first_prompt # loads address from memory, stores it in argument register 
    syscall    # reads register $v0 for op code, sees 4 and prints string located in $a0 

    # get input 
    li $v0, 5   # load op code for getting an integer from user into register $v0 
    syscall    # reads it and puts in $t0 
    move $s0, $v0  # $s0 saves it 


    # display prompt for q.2 
    li $v0, 4   # loads value 4 into register v0 which is op code for print string 
    la $a0, second_prompt # loads address from memory, stores it in argument register 
    syscall    # reads register $v0 for op code, sees 4 and prints string located in $a0 

    # get input 
    li $v0, 5   # load op code for getting an integer from user into register $v0 
    syscall    # reads it and puts in $v0 
    move $s1, $v0  # $s1 saves it 


    # display prompt for q.3 
    li $v0, 4   # loads value 4 into register v0 which is op code for print string 
    la $a0, operator # loads address from memory, stores it in argument register 
    syscall    # reads register $v0 for op code, sees 4 and prints string located in $a0 

    #get input 
    li $v0, 12   # load op code for getting an symbol from user into register $v0 
    syscall    # reads it and puts in $t0 
    move $s2, $v0  # $s0 saves it 


    # check symbol and use if statements to go to correct part in program 
    beq $s2, '*', Multiplication 
    beq $s2, '/', Division 
    beq $s2, '-', Subtraction 
    beq $s2, '+', Addition 

    # in case it is none of these 
    li $v0, 4    # print string value 4 
    la $a0, error_message # loads address from memory 
    syscall 


Multiplication: 

    # perform multiplication 
    mult $s0, $s1 
    mflo $s3 # moves product to $s3 
    syscall 

    jr Print 

Division: 

    # perform division 
    divu $s0, $s1 
    mflo $s3 # moves quotient to $s3 
    mfhi $s4 # move remainder to $s4 
    syscall 

    jr Print 

Subtraction: 

    # perform subtraction 
    sub $s3, $s0, $s1 # moves result to $s3 
    syscall 

    jr Print 

Addition: 

    # perform addition 
    add $s3, $s0, $s1 # moves result to $s3 
    syscall 

    jr Print 

Print: 
    # print new line 
    li $v0, 4 
    la $a0, nl 
    syscall 

    # print first number 
    li $v0, 1 # print int 
    move $a0, $s0 
    syscall 

    # print space 
    li $v0, 4 
    la $a0, sp 
    syscall 

    # print operator 
    li $v0, 11  # print operator 
    move $a0, $s2 
    syscall 

    # print space 
    li $v0, 4 
    la $a0, sp 
    syscall 

    # print second number 
    li $v0, 1  # print int 
    move $a0, $s1 
    syscall 

    # print equals 
    li $v0, 4 
    la $a0, eq 
    syscall 

    # jump to printing specifically for division 
    beq $s2, '/', Division_Print 

    # print result 
    li $v0, 1  # print int 
    move $a0, $s3 
    syscall 

    # print new line 
    li $v0, 4 
    la $a0, nl 
    syscall 

    jr Again_Prompt 

Division_Print: 
    # print quotient 
    li $v0, 1  # print int 
    move $a0, $s3 
    syscall 

    # print space 
    li $v0, 4 
    la $a0, sp 
    syscall 

    # print left parenthesis 
    li $v0, 4 
    la $a0, parl 
    syscall 

    # print remainder 
    li $v0, 1  # print int 
    move $a0, $s4 
    syscall 

    # print right parenthesis 
    li $v0, 4 
    la $a0, parr 
    syscall 

    # print new line 
    li $v0, 4 
    la $a0, nl 
    syscall 

    jr Again_Prompt 

Again_Prompt: 
    # display prompt 
    li $v0, 4   # loads value 4 into register v0 which is op code for print string 
    la $a0, again_prompt # loads address from memory, stores it in argument register 
    syscall    # reads register $v0 for op code, sees 4 and prints string located in $a0 

    # get input 
    li $v0, 12   # load op code for getting a character from user into register $v0 
    syscall    # reads it and puts in $t0 
    move $s6, $v0  # $s6 saves it 

    # print new line 
    li $v0, 4 
    la $a0, nl 
    syscall 

    # determine whether or not to do another calculation 
    beq $s6, 'y', loop 
    beq $s6, 'n', Terminate 

Terminate: 
    li $v0, 4   # loads value 4 into register v0 which is op code for print string 
    la $a0, ended_message # loads address from memory, stores it in argument register 
    syscall    # reads register $v0 for op code, sees 4 and prints string located in $a0 
    jr $ra 

回答

0

这里的问题是系统调用12,或者更确切地说,导致一个错误的假设来使用它。

暂时考虑syscall 12(读取char)的含义,它将从stdin 1字符返回。问题是这样的:

系统提示:What operation would you like to perform?,用户输入:+\n。由于stdin是行缓冲的,因此用户必须按下回车键,这意味着至少有两个字符放在缓冲区中,因为它们只有一个字符。这意味着,当你的程序继续到下一个查询:Do you want to go again?,仍然是在缓冲区一个字符:\n,这就是被第二系统调用12

现在你明白这个问题,我想回来你可以修复它。最好的方法是将读取的字符系统调用转换为读取字符串系统调用并检查输入的字符串。

作为一个松散的规则,不要使用系统调用12从键盘的用户输入。

+0

非常感谢。这现在是有道理的! – pearbear

相关问题