Assignment 6, Solutions
Part of
the homework for 22C:60, Fall 2009
|
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
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