# # program to compute square root using newton's method # .text .globl main main: # # opening linkage (save return address) # addi $sp, $sp, -4 sw $ra, 0($sp) # # in C-like pseudocode: # (no way to check for input errors with SPIM system calls, alas) # float input, guess, threshold; # int iter, maxiter; # scanf("%f %f %d", &input, &threshold, &maxiter) # if (input < 0) { # printf("Negative input not allowed") # } else { # guess = input # iter = 0 # while ((fabsf(guess*guess - input) > threshold) && (iter < maxiter)) { # guess = (guess + (guess/input)) / 2 # iter += 1 # } # printf("(input, result, iterations) = (%f, %f, %d\n", input, result, iter); # } # # register usage: # input in $f2 # threshold in $f4 # result in $f6 # guess in $f8 # maxiter in $s0 # iter in $s1 # # prompt # la $a0, prompt li $v0, 4 # "print string" syscall syscall # # get input # li $v0, 6 # "read float" syscall syscall mov.s $f2, $f0 # $f2 <- input # li $v0, 6 # "read float" syscall syscall mov.s $f4, $f0 # $f4 <- threshold # li $v0, 5 # "read int" syscall syscall addi $s0, $v0, 0 # $s0 <- maxiter # # check for negative input # mtc1 $zero, $f0 # $f0 <- 0 cvt.s.w $f0, $f0 # $f0 <- 0.0 c.lt.s $f2, $f0 # input < 0? bc1f notzero la $a0, errmsg li $v0, 4 # "print string" syscall syscall j end notzero: # # initialization: # # 2 in $f8 (for dividing by 2) # guess = input # iter = 0 li $t0, 2 mtc1 $t0, $f8 # $f8 <- 2 cvt.s.w $f8, $f8 # $f0 <- 2.0 mov.s $f6, $f2 # $f6 <- input # # main loop # looptest: # check for guess "close enough" mul.s $f0, $f6, $f6 # $f0 <- guess*guess sub.s $f0, $f0, $f2 # $f0 <- guess*guess - input abs.s $f0, $f0 # $f0 <- fabsf(guess*guess - input) c.le.s $f0, $f4 # check for <= threshold bc1t loopend # check for maximum iterations slt $t0, $s1, $s0 beq $t0, $zero, loopend # loop body div.s $f0, $f2, $f6 # $f0 <- input/guess add.s $f0, $f6, $f0 # $f0 <- guess + input/guess div.s $f6, $f0, $f8 # $f6 <- (guess + input/guess)/2 addi $s1, $s1, 1 # iter <- iter + 1 j looptest loopend: # # print results # la $a0, answer_txt1 li $v0, 4 # "print string" syscall syscall mov.s $f12, $f2 # get input li $v0, 2 # "print float" syscall syscall la $a0, sep # ", " li $v0, 4 # "print string" syscall syscall mov.s $f12, $f6 # get guess li $v0, 2 # "print float" syscall syscall la $a0, sep # ", " li $v0, 4 # "print string" syscall syscall addi $a0, $s1, 0 # get iter li $v0, 1 # "print int" syscall syscall la $a0, answer_txt2 li $v0, 4 # "print string" syscall syscall # # closing linkage (get return address and restore stack pointer) # end: lw $ra, 0($sp) addi $sp, $sp, 4 jr $ra .end main # # area for variables and constants # .data prompt: .asciiz "Enter input, threshold, maximum iterations:\n" errmsg: .asciiz "Negative input not allowed\n" answer_txt1: .asciiz "(input, result, iterations = (" sep: .asciiz ", " answer_txt2: .asciiz ")\n"