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