Computer Architecture Lab 06
Computer Architecture Lab 06
6 and Division
6.1 Objectives
Sequential binary multiplication is a simple but slow form of multiplication. It is performed using
addition and shift operations as illustrated in Figure 6.1. The multiplication of two 32-bit integers is a
64-bit product stored in two registers: HI and LO.
Register HI is initialized with the value 0, and LO is loaded with the value of the multiplier. The
sequential algorithm is repeated 32 times for each bit of the multiplier. Finally, the product is
computed in two registers HI and LO.
Signed multiplication can also be performed using the same sequential binary multiplier, but with
minor modification. When adding (HI + Multiplicand) the proper sign bit of the result is computed,
instead of the carry bit. When shifting the HI and LO registers to the right, the sign-bit is inserted to
the left of the product. Additions are used for the first 31 steps. However, the last step should use
subtraction (rather than addition), if the sign-bit of the multiplier is negative.
Sequential binary multiplication is slow because it requires one cycle for each bit of the multiplier.
Faster binary multiplication can be done in hardware, as shown in Figure 6.3. The cost of the binary
multiplier increases because it uses many adders, instead of just one used as in Figure 6.2.
Sequential binary division can be performed using shift and subtract operations. Binary division
produces a quotient and a remainder. It also uses two registers HI and LO. The quotient is computed
in the LO register and the remainder is computed in the HI register. HI is initialized with zero and
LO is initialized with the dividend. At each iteration step, registers HI and LO are shifted left by 1
bit. The difference: (HI – Divisor) is computed. If this difference is ≥ 0, the Remainder (HI register)
is set equal to the difference and the least significant bit of the quotient (LO register) is set to 1. The
sequential binary division algorithm is repeated 32 times, as shown in Figure 6.4.
A simple but slow sequential binary divider is shown in Figure 5.5. It uses a 32-bit ALU that does
subtraction. It also uses HI and LO registers, a Divisor register, and simple control logic to shift left
the HI and LO registers and set the least-significant bit of LO. The control logic repeats 32 times to
compute each bit of the quotient in LO. The final remainder will be in the HI register.
Multiplication and division generate results that are larger than 32 bits. Multiplication produces a
64-bit product while division produces a 32-bit quotient and a 32-bit remainder. The MIPS
architecture provides two special 32-bit registers that are the target for integer multiply and divide
instructions. The source operands come from the general-purpose register file. However, the results
are written into HI and LO registers. For multiplication, the HI and LO registers form a 64-bit
product. For division, HI stores the 32-bit remainder, while LO stores the 32-bit quotient.
MIPS defines two multiply instructions: mult for signed multiplication and multu for unsigned
multiplication. Both multiply instructions produce a 64-bit product without overflow. There is also
a third mul instruction that computes the same 64-bit product as a mult instruction in HI and LO
registers. However, the mul instruction also copies the LO register into destination register Rd. The
mul instruction is useful when the product is small and can fit in a 32-bit destination register.
In addition, MIPS defines two integer divide instructions: div for signed division and divu for
unsigned division. The quotient of the integer division is saved in the LO register, while the
remainder is saved in the HI register as shown in Table 6.2.
If the divisor in register Rt is zero, then the MIPS divide instructions do not compute any result in
the HI and LO registers. Division by zero is ignored and no exception is produced. The MIPS
programmer must ensure that the divisor is non-zero when using the integer divide instruction.
Special instructions are used to move data between the HI and LO registers and general-purpose
registers. These are listed in Table 6.3.
Raising an integer number x to a power n (xn), may be computed using successive multiplications.
The following code uses integer multiplication to implement the power function. Registers $a0 and
$a1 are used to store x and n, while $v0 contains the result.
li $a0, 7 # number x
li $a1, 5 # number n
li $v0, 1 # $v0 = 1
pow:
mul $v0, $v0, $a0 # $v0 = $v0, $a0
addiu $a1, $a1, -1 # decrement n
bnez $a1, pow # loop if (n != 0)
The following MIPS loop computes the gcd of two numbers stored in registers $a0 and $a1. The
final result is computed in register $a0.
li $a0, 30 # number a
li $a1, 18 # number b
gcd:
div $a0, $a1 # HI = remainder, LO = quotient
move $a0, $a1 # $a0 = number b
mfhi $a1 # $a1 = a % b (remainder)
bnez $a1, gcd # loop if (b != 0)
.text
main:
la $t0, str # load address of str into $t0
li $v0, 0 # Initialize $v0 = 0
li $v1, 10 # Initialize $v1 = 10
lb $t1, ($t0) # load byte: $t1 = Memory($t0)
str2int:
addiu $t1, $t1, -48 # convert character to a number
mul $v0, $v0, $v1 # $v0 = $v0 * 10
addu $v0, $v0, $t1 # $v0 = $v0 + digit
addiu $t0, $t0, 1 # point to next character in memory
lb $t1, ($t0) # load byte: $t1 = Memory($t0)
bnez $t1, str2int # loop back if not NULL character
done:
. . . # $v0 = integer result
An unsigned integer can be converted to a string by successive divisions by 10. The remainder is a
digit between 0 and 9. The remainder digits are computed backwards starting at the least significant
digit. Each remainder is then converted to an ASCII character and stored in memory in a string. For
example, consider converting the integer 5218 into a string. This can be done as follows:
5128 / 10 = 512, 5128 % 10 = 8 Convert 8 into character '8'
512 / 10 = 51, 512 % 10 = 2 Convert 2 into character '2'
51 / 10 = 5, 51 % 10 = 1 Convert 1 into character '1'
5 / 10 = 0, 5 % 10 = 5 Convert 5 into character '0'
Stop when the quotient is zero
The following MIPS code converts an unsigned integer stored in register $a0 into a string stored in
the data segment in memory. The string is initialized with 10 space characters. The string has 10
characters only because a 32-bit unsigned integer can have at most 10 digits.
1. Write MIPS code to perform the following integer multiplications. What is the value of the LO
and HI registers?
a) 98765 × 54321 using the multu instruction
b) -98765 × -54321 using the mult instruction
2. Write MIPS code to perform the following integer divisions. What is the value of the LO and HI
registers?
a) 98765 / 54321 using the divu instruction
b) -98765 / -54321 using the div instruction
3. Factorial Calculation: Using the mul instruction, write a MIPS program that computes the
factorial of a number n input by the user, and display the result on the screen. Run your code
and record the maximum 32-bit factorial value that can be computed without errors.
4. The string-to-integer program presented in Section 6.5 converts a string of decimal digits to an
unsigned integer using successive multiplications by 10 and additions. It is also possible to
convert a string of digits in any radix system to an integer, using successive multiplications by
the radix value and additions. Rewrite the string-to-integer program asking the user to input a
5. The integer-to-string program presented in Section 6.5 converts an unsigned integer to string
format using successive division by 10 and storing the remainder digit characters in a string. It
is also possible to convert the unsigned integer to any radix using successive divisions by the
radix value. Rewrite the integer-to-string program asking the user to input an unsigned integer
and a radix value between 2 and 10. Do the radix conversion and then print the string. Make
sure that the string has sufficient space characters, especially when converting to radix 2.
6. Fraction computation: Using successive integer multiplications and divisions, write a MIPS
program that divides an integer x by another integer y that are read as input. The result of the
division should be in the form: a.b, where a is the integer part and b is the fractional part.
Compute the fraction b with 8 digits after the decimal point. Display the result in the form a.b.