rss
twitter
facebook

Home

calculation is recursive.

# This file can be used to write all the programs in PCSpim
# NAME:
# TA's NAME:
# DESCRIPTION:

## Example program in revised section 9.7 of Goodman and
## Miller's "A Programmer's View of Computer Architecture"
##

## This MAL program computes the greatest common divisor of
## two positive integers. The function that does the main
## calculation is recursive.

        .data
# data items, i.e. all initialized and
# non-initialized items go in here

err_msg:     .asciiz "\nbad integer entered\n"

        .text
        .globl main

main:       

# your main subroutine code goes in here

        jal intro
        jal getint
        beqz $v0, input_err
        move $s0, $v1
        jal getint
        beqz $v0, input_err
        move $a1, $v1
        move $a0, $s0
        jal gcd
        move $a0, $v0
        jal print_result
        done

input_err:    la $8, err_msg
        puts ($8)

# the last line of main
        done

# end of main
# any subroutines may be inserted here:...

## Intro
## A simple procedure to print a little introduction message.
## There are no parameters.

        .data
msg1:    .asciiz "This program computes the greatest common divisor of \n"
msg2:    .asciiz "two user entered integers.\n\n"

        .text
intro:        la $8, msg1
        puts ($8)
        la $8, msg2
        puts ($8)
        jr $ra

## getint
## A function to get a single positive integer from the user.
## return values:
##  $v0 -- flag indicating success of the function
##         value is 1 if integer entered is ok.
##         value is 0 if not ok.
##  $v1 -- the integer entered
##
## register assignments:
##  $8 -- user entered character
##  $9 -- digit of integer
##  $10 -- newline character (the constant)
##  $11 -- the integer being entered
##  $12 -- the constant 10, the base
##  $13 -- temp
##  $14 -- the constant 9

        .data
prompt:        .asciiz "Enter positive integer: "

        .text
getint:        li $10, 10     # $10 <- newline character
        li $12, 10    # constant 10
        li $11, 0
        li $14, 9
        la $13, prompt
        puts ($13)

getchar:    getc $8
        beq $8, $10, getint_rtn
        sub $9, $8, 48
        bgt $9, $14, int_err
        bltz $9, int_err
        mul $11, $11, $12
        add $11, $11, $9
        b getchar

getint_rtn:    li $v0, 1
        move $v1, $11
        jr $ra

int_err:    li $v0, 0
        jr $ra

##  gcd
##  A recursive function to calculate the greatest common divisor.
##
##    gcd(m, n) = m            if n = 0
##              = gcd (n, m mod n)     if n > 0
##  return values:
##    $v0 -- the greatest common divisor
##  parameters:
##    $a0 -- m
##    $a1 -- n
##

        .data
gcd_err_msg:    .asciiz "error in calculating gcd -- quitting.\n"

        .text

gcd:        sub $sp, $sp, 12    # allocate activation record
        sw $ra, 12($sp)        # save return address
        bgtz $a1, n_greater
        bnez $a1, gcd_err
        move $v0, $a0        # return m
        b gcd_rtn

n_greater:    sw $a0, 8($sp)        # save current parameters
        sw $a1, 4($sp)
        rem $8, $a0, $a1
        move $a0, $a1        # set up parameters for call
        move $a1, $8
        jal gcd            # recursive call to gcd
        lw $a0, 8($sp)        # restore current parameters
        lw $a1, 4($sp)
            # return value already in $v0

gcd_rtn:    lw $ra, 12($sp)        # restore return address
        add $sp, $sp, 12    # remove activation record
        jr $ra            # return

gcd_err:    la $8, gcd_err_msg
        puts ($8)
        done

## print_result
##  Procedure to print out the base ten integer passed to the procedure
##  as a parameter
##
## return values:
##  none
## parameters:
##  $a0 -- the integer to be printed out
##
## register assignments:
##  $8 -- address of output string
##  $9 -- stack pointer before pushing characters onto stack
##  $10 -- copy of integer to be printed
##  $11 -- ASCII character code of digit to be printed as pushed
##  $12 -- ASCII character code of digit to be printed as popped
##  $13 -- newline character for nice output

        .data
result_msg:    .asciiz "The greatest common divisor is "

        .text
print_result:    move $10, $a0
        la $8, result_msg
        puts ($8)
        move $9, $sp
        bnez $10, push_loop
        li $11, 0        # special case for printing 0
        sw $11, 0($sp)
        sub $sp, $sp, 4
        b print_loop

push_loop:    rem $11, $10, 10    # push characters onto stack
        add $11, $11, 48
        sw $11, 0($sp)
        sub $sp, $sp, 4
        div $10, $10, 10
        bnez $10, push_loop

print_loop:    add $sp, $sp, 4        # pop characters off stack
                    # and print

        lw $12, 0($sp)
        putc $12
        bne $9, $sp, print_loop
       
        li $13, 10         # print newline
        putc $13
        jr $ra

# END OF PROGRAM (leave this line here)

0 comentários:

 
Powered by Blogger