! ****************************************************************************
! 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