Assignment 6, Solutions

Part of the homework for 22C:60, Fall 2009
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

  1. Background: The Hawk monitor includes a routine, DIVU, that returns the quotient (and remainder) after division of one unsigned integer by another. The operands are 32-bit unsigned integers. There is no DIV routine in the monitor for taking the quotient of signed integers. The Hawk monitor really would be nicer if it also contained this routine (specified in the style of the interface specifications in monitor.h)
            EXT     DIV     ; divide two signed integers
                            ;   takes R3=dividend R4=divisor
                            ;   returns R3=quotient
                            ;   may wipe out R4-7
    

    Also, recall that, in elementary school math, we were taught that:

            (-A)/B = -(A/B)
            A/(-B) = -(A/B)
            (-A)/(-B) = A/B
    

    (There are real problems with the above definition of division involving negative integers, but the above will suffice for now).

    A problem: Write a subroutine that conforms to the above interface spec. It should operate by taking the absolute value of any negative operands, then dividing by a call to DIVU, and finally, negating the quotient if the signs of the operands require this. (1.5 points)

    Note. The logic of the program would be trivial in a high level language, just 3 if statements and a subroutine call. The hard part is that it involves one subroutine calling another, and it involves local variables. You are not required to assemble or run your code, just turn in legible, correct and appropriately commented assembly language for the subroutine itself.

    ; activation record
    ;RETADD =       0
    R8SV    =       4       ; use LSB of R8 to remember if quotient needs negation
    ARSIZE  =       8
    
    DIV:    ; divide two signed integers
            ;   takes R3=dividend R4=divisor
            ;   returns R3=quotient
            ;   may wipe out R4-7
            STORES  R1,R2           ; save return address
            STORE   R8,R2,R8SV      ; save R8
            LIS     R8,0            ; negate = 0
    
            ; take absolute values of operands, recording need to negate quotient
            TESTR   R3
            BNR     IDNDEI          ; if (dividend < 0) {
            NEG     R3,R3           ;   dividend = - dividend
            ADDSI   R8,1            ;   negate = negate + 1
    IDNDEI:                         ; }
            TESTR   R4
            BNR     ISOREI          ; if (divisor < 0) {
            NEG     R4,R4           ;   divisor = - divisor
            ADDSI   R8,1            ;   negate = negate + 1
    ISOREI:                         ; }
    
            ; divide the absolute values
            ADDSI   R2,ARSIZE
            LIL     R1,DIVU
            JSRS    R1,R1           ; unsigned divide R3 = R3 / R4
            ADDSI   R2,-ARSIZE
    
            ; negate the quotient
            BITTST  R8,0
            BCS     QUOTEI          ; if (negate is odd) {
            NEG     R3,R3           ;   quotient = - quotient
    QUOTEI:                         ; }
    
            ; cleanup and return
            LOAD    R8,R2,R8SV      ; restore R8
            LOADS   R1,R2           ; restore return address
            JUMPS   R1              ; return
    

  2. Background: Here is a stupid way to add two unsigned integers:
            unsinged int add( unsigned int a, unsigned int b )
            {
                unsigned int sum;
                if (b = 0) {
                    sum = a;
                } else {
                    sum = add( a + 1, b - 1 );
                }
                return sum;
            }
    

    A problem: Write equivalent SMAL Hawk code. (1.5 points)

    Note. This problem is actually easier than part a, but it is recursive. Small optimizations to your code can markedly improve readability. You are not required to assemble or run your code, just turn in legible, correct and appropriately commented assembly language for the subroutine itself.

    ; activation record structure        
    ;RETAD  =       0
    ARSIZE  =       4
    
    ADD:    ; add two integers
            ; expects R3 and R4 as operands
            ; returns R3, the sum
            STORES  R1,R2           ; save return address
            TESTR   R4
            BZS     ADDQT           ; if (R4 != 0) {
            ADDSI   R3,1            ;   R3 = R3 + 1
            ADDSI   R4,-1           ;   R4 = R4 - 1
            ADDI    R2,R2,ARSIZE
            JSR     R1,ADD          ;   R3 = add( R3, R4 )
            ADDI    R2,R2,-ARSIZE
    ADDQT:                          ; }
            ; the sum is in R4
            LOADS   R1,R2           ; restore return address
            JUMPS   R1              ; return