All pastes #914821 Raw Edit

k4st

public text v1 · immutable
#914821 ·published 2008-02-23 05:53 UTC
rendered paste body
! ****************************************************************************
! Peter Goodman
! Student ID: 250 379 503
! Assignment: 3
! File: divide.m:
! Description:
!   Perform 32 bit signed integer division.
!
!   To determine the sign of the quotient, one can test the high order bits
!   and xor them. If both zero, then result (0) is positive. If one is
!   negative, then the result (1) is negative. If both are negative, then the
!   result (0) is positive.
!
!   Given that we can test if we are working with negative numbers, we can take
!   advantage of the unsigned integer division algorithm and negate registers
!   where necessar. Then, negate the final answer if necessary.
! ****************************************************************************

! macro definitions

define(divisor_r, l0)
define(quotient_r, l1)
define(remainder_r, l2)
define(garbage_r, g0)

define(bit_counter_r, l3)
define(negative_test_r, l4)

define(PROMPT, '>')
define(NEW_LINE, '\n')
define(DIVIDE_BY_ZERO, 'X')

define(LOW_ORDER_BIT, 1)
define(NUM_BITS, 32)

! begin program

    .global main

main:   
    save %sp, -96, %sp
    
    /* Initialize the registers */
    mov 0, %divisor_r
    mov 0, %remainder_r
    mov 0, %negative_test_r
    mov NUM_BITS, %bit_counter_r
    
    /* Display a prompt and begin reading in a division expression */
    
    call writeChar                              ! write out the prompt
    mov PROMPT, %o0
    
    call readInt                                ! read in the numerator
    nop
    mov %o0, %quotient_r
    
    /* Check to see if numerator is negative, if so, set %negative_test_r to
       1, i.e. true.
     */
    addcc %quotient_r, %quotient_r, %garbage_r
    bcc 1f
    nop
    
    neg %quotient_r                             ! negate the quotient
    mov 1, %negative_test_r 
    
1:  call readChar                               ! ignore the '/'
    nop
    
    call readInt                                ! read in the denominator
    nop
    mov %o0, %divisor_r
    
    /* Check to see if denominator is negative, if so, XOR with
       %negative_test_r to see if the result of divison will be positive or
       negative.
     */ 
    addcc %divisor_r, %divisor_r, %garbage_r
    bcc 2f
    nop
    
    /* We got a negative number, XOR with negative_test_r to see if final
       result of division will be zero or 1.
     */
    neg %divisor_r
    xor %negative_test_r, 1, %negative_test_r

    /* check for division by zero, skip over to return error */
2:  addcc %divisor_r, 0, %garbage_r
    be error
    nop
    
    /* Shift quotient_r one bit left, moving its high order bit into the
       remainder_r.
     */
divide:             
    
    add %remainder_r, %remainder_r, %remainder_r
    addcc %quotient_r, %quotient_r, %quotient_r
    
    bcc 1f                                      ! the MSB was 0, ignore
    nop
    
    bset LOW_ORDER_BIT, %remainder_r            ! set the LSB

    /* Subtract the divisor from the remainder. If the result is:
        negative: ignore
        positive: set the LSB of the quotient to 1
    */
1:  subcc %remainder_r, %divisor_r, %remainder_r
    
    bneg 2f
    nop
    
    bset LOW_ORDER_BIT, %quotient_r             ! set the LSB of the quotient
                                                ! when remainder_r > divisor_r

    ba 3f
    nop
    
2:  add %divisor_r, %remainder_r, %remainder_r  ! restore it

    /* The bit counter keeps track of how many bits we've modified. When the
       counter reaches zero, we are done.
     */
3:  subcc %bit_counter_r, 1, %bit_counter_r
    be success
    nop
    
    /* Bit counter is greater than zero, go back and continue to divide. */
    
    ba divide                                   ! repeat the division process
    nop
    
    /* Division algorithm has successfully completed. See if the quotient
       needs to be negated, if so do that. Then, print out the quotient on one
       line, followed by the remainder on another line.
     */
success:
    
    /* Modify the sign of the quotient if necessary */
    orcc %negative_test_r, 0, %garbage_r
    be 1f
    nop
    
    /* quotient needs to be negative, so negate it */
    neg %quotient_r
    
    /* write out the final results. */
1:  call writeInt                               ! print out the quotient
    mov %quotient_r, %o0
    
    call writeChar
    mov NEW_LINE, %o0                           ! print a new line
    
    call writeInt                               ! print the remainder
    mov %remainder_r, %o0
    
    ba done                                     ! done
    nop
    
    /* If there is a division-by-zero error, we will end up here. */
error:                                  
    call writeChar
    mov DIVIDE_BY_ZERO, %o0                     ! show 'X' as the error

done:
    
    call writeChar                              ! print a new line
    mov NEW_LINE, %o0
    
    ret                                         ! done.
    restore