# # 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) # # double input, guess, threshold; # int iter, maxiter; # /* code to input values */ # if (input < 0) { # /* print error message */ # } else { # guess = input # iter = 0 # while ((fabs(guess*guess - input) > threshold) && (iter < maxiter)) { # guess = (guess + (guess/input)) / 2 # iter += 1 # } # /* code to print values */ # } # # 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, 7 # "read double" syscall syscall mov.d $f2, $f0 # $f2 <- input # li $v0, 7 # "read double" syscall syscall mov.d $f4, $f0 # $f4 <- threshold # li $v0, 5 # "read int" syscall syscall addi $s0, $v0, 0 # $s0 <- maxiter # # check for negative input # li.d $f12, 0.0 c.lt.d $f2, $f12 # input < 0.0? bc1f input_okay la $a0, errmsg li $v0, 4 # "print string" syscall syscall j end input_okay: # # initialization: # # guess = input # iter = 0 mov.d $f6, $f2 li $s1, 0 # # main loop # looptest: # check for guess "close enough" mul.d $f12, $f6, $f6 # $f12 <- guess*guess sub.d $f12, $f12,$f2 # $f12 <- guess*guess - input abs.d $f12, $f12 # $f12 <- fabs(guess*guess - input) c.le.d $f12, $f4 # check for <= threshold bc1t loopend # check for maximum iterations slt $t0, $s1, $s0 beq $t0, $zero, loopend # loop body div.d $f12, $f2, $f6 # $f12 <- input/guess add.d $f12, $f6, $f12 # $f12 <- guess + input/guess li.d $f14, 2.0 div.d $f6, $f12, $f14 # guess <- (guess + input/guess)/2 addi $s1, $s1, 1 # iter <- iter + 1 j looptest loopend: # # print results # la $a0, input_txt li $v0, 4 # "print string" syscall syscall mov.d $f12, $f2 # get input li $v0, 3 # "print double" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall la $a0, result_txt li $v0, 4 # "print string" syscall syscall mov.d $f12, $f6 # get guess li $v0, 3 # "print double" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall la $a0, iter_txt li $v0, 4 # "print string" syscall syscall addi $a0, $s1, 0 # get iter li $v0, 1 # "print int" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall la $a0, sqrt_txt li $v0, 4 # "print string" syscall syscall sqrt.d $f12, $f2 # compute sqrt(input) li $v0, 3 # "print double" syscall syscall la $a0, nl li $v0, 4 # "print string" syscall syscall la $a0, diff_txt li $v0, 4 # "print string" syscall syscall sub.d $f12, $f12, $f6 # compute difference li $v0, 3 # "print double" syscall syscall la $a0, nl 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 (one value per line):\n" errmsg: .asciiz "Negative input not allowed\n" input_txt: .asciiz "input = " result_txt: .asciiz "result = " iter_txt: .asciiz "iterations = " sqrt_txt: .asciiz "result of sqrt instruction = " diff_txt: .asciiz "difference = " nl: .asciiz "\n"