2014-03-03 67 views
4

我想完成这个MIPS计算器,超级基本,我的第一个mips程序。它不必处理溢出或类似的东西,只需要处理小的正数。MIPS计算器

我没有检查我的算法乘法和除法,因为我只是试图让增加工作。

我不能为了我的生活弄清楚为什么整数不会读入,并且当我调用lb $ a0时,我得到的内存超出界限,op显示操作符输出并且不理解为什么。

我对此很陌生,所以任何事情都可能有帮助。提前致谢。

 .data 
         # const string for welcome 
welc:  .asciiz "Welcome to SPIM Calculator 1.0!\n" 
p_int:  .asciiz "\nPlease give an integer: " 
p_op:  .asciiz "\nPlease give an operator: " 
i_err:  .asciiz "\nInput Incorrect, bad operator!\n" 
again_str: .asciiz "Another calculation? (y/n)" 
rmndr:  .asciiz " r: " 
new_line: .asciiz "\n" 

int1: .word 1   # space to hold int 1 
int2: .word 1   # space to hold int 2 
raw_in: .space 1  # space to hold raw input 
op:  .space 1  # space to hold operator char 
a_char: .space 1  # space to hold again char 

out: .word 1   # space to hold output 
remain: .word 1   # space to hold remainder 

#operator constants 
c_plus: .ascii "+"  # const for + 
c_min: .asciiz "-"  # const for - 
c_mult: .asciiz "*"  # const for * 
c_divi: .asciiz "/"  # const for/
c_eq: .asciiz "="  # const for = 
c_no: .asciiz "n"  # const for n 

     .text 
     .globl main 
main: li $v0, 4    # syscall 4, print string 
     la $a0, welc   # give argument: string 
     syscall     # actually print string 

calc: la $t6, remain   # load remainder variable 
     move $t6, $zero   # store 0 in remainder (reset) 

     li $v0, 4    # syscall 4, print string 
     la $a0, p_int   # give argument: string 
     syscall     # actually print string 

     li $v0, 5    # tell syscall we want to read int 1 
     syscall     # actually read in int 1 
     la $s1, int1   # load int1 into $s1 
     move $s1, $v0   # copy the integer from $v0 to int1 

     li $v0, 4    # syscall 4, print string 
     la $a0, p_int   # give argument: string 
     syscall     # actually print string 

     li $v0, 5    # tell syscall we want to read int 2 
     syscall     # actually read in int 2 
     la $s2, int2   # give $s2 the address to hold int 2 
     move $s2, $v0   # copy the integer from $v0 to $s2 

     li $v0, 4    # syscall 4, print string 
     la $a0, p_op   # give argument: string 
     syscall     # actually print string 

     li $v0, 8    # tell syscall we want to read operator 
     la $a0, op    # give $a0 the address to hold the operator 
     syscall     # actually read in operator 

     lb $t0, op    # load the first byte of op 
     li $t1, '+'    # load const for plus 
     li $t2, '-'    # load const for minus 
     li $t3, '*'    # load const for multiplying 
     li $t4, '/'    # load const for dividing 

     la $s0, out    # load out to $s0 

     beq $t0, $t1, plus  # we're adding 
     beq $t0, $t2, minus  # we're subtracting 
     beq $t0, $t3, multi  # we're multiplying 
     beq $t0, $t4, divi  # we're dividing 
     # else 
     j error     # incorrect input 

plus: add $s0, $s1, $s2  # add our ints, store in $t0 
     j print 

minus: sub $s0, $s1, $s2  # subtract our ints, store in $t0 
     j print 

multi: slt $t1, $t2, $s2  # if our counter is less than int2, set $t1 to 1 
     beq $t1, $zero, print # if we've reached int2, we're done 
     add $s0, $s1, $s1  # add int1 and int1, store in out 
     j multi     # loop 

divi: la $t0 remain   # load remainder into $t0 
     move $t0, $s1   # set remainder to dividend 
     add $s0, $zero, $zero # set out to 0, just in case 
loop: slt $t1, $t0, $s2  # if remainder is less than divisor, set 1 
     beq $t1, $zero, print # if we're done branch to done 
     sub $t0, $t0, $s2  # sub divisor from remainder, store in remainder 
     addi $s0, $s0, 1  # increment quotient by 1 
     j loop     # loop 

print: li $v0, 1    # tell syscall we want to print int 
     la $a0, int1   # give syscall int1 to print 
     syscall     # actually print int 
     li $v0, 4    # tell syscall we want to print string 
     lb $a0, op    # tell syscall we want to print operator 
     syscall     # actually print string 
     li $v0, 1    # tell syscall we want to print int 
     la $a0, int2   # give syscall int2 to print 
     syscall     # actually print int 
     li $v0, 4    # tell syscall we want to print string 
     la $a0, c_eq   # tell syscall we want to print operator 
     syscall     # actually print string 
     li $v0, 1    # tell syscall we want to print integer 
     la $a0, out    # give syscall our output 
     syscall     # actually print int 
     la $t0, remain   # load remainder 
     beq $t0, $zero, again # if we have no remainder, finish printing 
     li $v0, 4    # tell syscall we want to print string 
     la $a0, rmndr   # tell syscall we want to print remainder string 
     syscall     # print "r: " 
     li $v0, 1    # tell syscall we want to print int 
     la $a0, remain   # give syscall our remainder to print 
     syscall     # print remainder 

again: li $v0, 4    # tell syscall we want to print string 
     la $a0, new_line  # tell syscall to print new line 
     syscall 
     la $a0, again_str  # load prompt for again string for syscall 
     syscall 
     li $v0, 8    # tell syscall we want to read string 
     la $a0, a_char   # tell syscall to put it in $a0 
     syscall 
     lb $t0, a_char 
     li $t1, 'n'    # get n char so we can compare 
     beq $t0, $t1, exit  # if we are done, exit 
     #else loop 
     j calc     # jump to beginning 



error: li $v0, 4    # tell syscall we want to print string 
     la $a0, i_err   # give syscall what to print 
     syscall     # actually print 
     j again     # go to prompt for retry 

exit: li $v0, 10    # exit code 
     syscall     #exit! 

screenshot

回答

3

的问题是,你不使用适当的指令来处理内存。

  1. 相反的move你应该使用sw(存储字)。此代码将不是int存储到int1

    la $s1, int1   # load int1 into $s1 
    move $s1, $v0   # copy the integer from $v0 to int1 
    

    相反,你应该写:

    la $s1, int1   # load address of int1 into $s1 
    sw $v0, 0($s1)   # copy the integer from $v0 to int1 
    
  2. 像储存,从内存中加载需要两条指令:

    la $s1, p_op    # or whatever register you choose to use 
    lb $a0, 0($s1)   # load byte from the address stored in $s0 (in index 0) 
    

    ,如果你想要将p_op的地址加载到$a0中,则应该使用la $a0, p_op而不是lb