Write Up
Write Up
Abstract—This write up explains the implementation of basic once, load each of them separately. After all the files have
math operations, including addition, subtraction, multiplication been loaded and opened, MARS should look like this.
and division, using the MIPS logical and normal procedures in
Mars 4.5. Pictures of the code are included to help understand
the program.
I. INTRODUCTION
Fig.1. Opening/loading files onto MARS
D. Binary 2) Multiplication
Binary is a number system with base 2, unlike the decimal For unsigned multiplication, a counter ($t0) is initially set to
system, which uses base 10. Since this system is base 2, it 0. The first input, which is the multiplicand, is saved in a
consists of only 2 symbols that can be used, 0 or 1. For temporary register ($t4). The second input, which is the
example, if we used a 4 bit long word, 0 is represented as 0000 multiplier, is put into a temporary register ($t1). This
and 1 is represented as 0001. Once a digit reaches 1, it represents the lo of the multiplication. The high is initially set
becomes 0 and rolls over to the next larger digit and places a 1 to 0 and put into temporary register $t2.
there. Thus, 2 would be represented as 0010. The binary In short, binary multiplication is simply repeated addition.
system is extremely useful when it comes to computers as a What we must know is that 0 x 0 = 0, 1 x 0 = 0, and 1 x 1 = 1.
computer system can only read 1’s and 0’s. If the current bit of the multiplier is 0, then 0 gets placed in
that bit position of the answer. If the multiplier is 1, then
Now the question is, how does one represent a negative simply put the multiplicand into that bit position of the
number in binary? This is where the “two’s compliment” answer.
form comes into play. In two’s compliment, if a 1 exists in the
MSB position, that means the number is negative. If a 0 exists 3) Division
in the MSB position, then the number is positive. For First, we must align the divisor with the MSB bits of the
example, 3 in twos compliment is 0011, where as -3 is 1101. dividend. Compare these bits to the divisor. If these bits are
To obtain the negative of a number, inverse all the bits of the greater than the divisor, the quotient bit is set to 1 and then
positive number and add 1. If we inverse all the bits of +3, we subtraction is performed with MSB bits – divisor. If the MSB
get 1100. Add 1 to this, and we obtain 1101, which is -3. bits are less than the divisor, the quotient bit is set to 0 and
subtraction is not performed. The divisor is then shifted one
III. DESIGN AND IMPLEMENTATION bit to the right and we compare the MSB bits to the divisor
again. This continues until division is over.
Section 3 discusses the design of the arithmetic calculator
and how it’s being implemented in MIPS. This calculator
implements addition, subtraction, multiplication, and division B. Implementation
operations. To implement the calculator operations, many macros and
utility procedures are designed to help make the
A. Design implementation easier.
The design section talks about the design of the addition,
subtraction, multiplication, and division operations. 1) Utility Macros
The 4 macros created are extract_nth_bit, insert_to_nth_bit,
1) Addition and subtraction store_stack_all, and restore_stack_all.
Addition and subtraction both relate in the sense that
subtraction is the addition of the negation of the second i. Extract_nth_bit
integer. For example, A-B = A + (-B). For the addition The extract_nth_bit macro obtains a bit value at a given
operation, a full adder must be implemented since the carry bit position for any integer.
has to be taken into consideration. A half adder can only add
two bits.
The way addition works is a carry bit starts off as 0 and is
added with the LSB bits of the two inputs. The sum is put into
the LSB position of the answer, and the carry bit is found and
added to the next two bits of the inputs. To get the nth digit,
the logical XOR is called on the first bits and is stored. Then,
the logical XOR is called on the stored value and the carry in. The macro contains three arguments passed in as regD,
This results in the sum bit and is stored temporarily. To find regS, regT. regD is the destination register where the
the carry bit, first initialize the carry bit to 0. To find the carry result will be stored. regS is the source register which
bit, first we use the XOR operation on the two inputs and store contains the bit pattern which the calculator will be
it in lets say $t7. AND is called on $t7 and the initial carry bit extracting from. regT holds the position of the bit that
($v1) and is stored in $t8. Then, AND is used on the nth bits will be extracted.
of the two inputs. Finally, OR is called on $t8 and $t1 and is First, $regS is moved into $s0 just so that the original
stored back in the carry bit register which is $v1. source register does not get messed up. Then, $s0 is
These operations are performed 32 times, since there are 32 shifted right by the bit position number and is stored back
bits in each register. Finally, the sum of the two inputs will be into $s0. Finally, AND is used on $s0 and 1 to extract
calculated. the bit and is put into the destination register. Basically,
For subtraction, the only change that must be made is the if $s0 is 0x0, AND’ing it with 1 will result in 0. If $s0, is
complement of the second input must be taken. Then pass the 0x1, AND’ing it with 1 will result in 1. This properly
first input and the complement of the second input into the add extracts the needed bit.
loop and the difference (in this case a sum) will be calculated.
ii. Insert_to_nth_bit
CS47 3
ii. Twos_complement_if_neg
Twos_complement_if_neg branches to
twos_complement if the argument is less than 0, or
returns the argument itself if it is above 0.
CS47 4
iii. Twos_complement_64bit
Twos_complement_64bit returns the complement of the
lo and hi of the multiplied result. The lo exists in the $a0
register and the hi exists in the $a1 register.
$a0 and $a0 are inverted using not. $a1 is then saved in
$a3 and 1 is loaded into $a1. Add_loop is then called on $a0
and $a1, which is the lo and 1 respectively. Once add_loop is
done, twos_complement_64bit is returned to and the answer
($v0) is stored in $t0. The carry bit ($v1) is saved in $a1 and
$a3 is moved back into $a0. Add_loop is then called again
with the new $a0 and $a1. After this, the
twos_complement_64bit is done.
3) Addition/subtraction implementation
CS47 5
3) Multiplication implementation
i. Multiplication_au_logical
Multiplication_au_logical sets up the entire
multiplication process. It first checks to see if both number
are negative by using twos_complement_if_neg, then jumps
to mul_unsigned.
Mul_unsigned gets all the necessary registers needed for
storage and continues on to extract_beginning.
Extract_beginning first gets the 0th bit of the lo and stores it
in $a0. $a0 is then replicated using bit_replicator and is
stored in $v0. AND is then called on the replicated bit
pattern and $t4, which holds $a0 (MCND). Now we want
to add the original Hi with the mcnd or 0, depending on
what the 0th bit was, and the value is stored back into the
register, which holds the Hi. Next, the Lo is shifted right by
1 bit and the 31st bit of Lo gets the 0th bit of the Hi. Then,
the Hi is shifted right by 1 bit and the counter is
incremented by 1. Next, we check if the counter equals 32,
and if it does, that means all the multiplicating is over and
we jump to “done_mult”. If it does not equal 32, we jump
back to the “extract_beginning”.
ii. done_mult
Done_mult begins with storing the lo ($t1) into $v0 and
storing the hi ($t2) into $v1. Next, the code finds out if one
of the initial inputs were negative or if both are either
positive or negative. We check to see if both are negative
or if both are positive by calling an XOR on the 31st bit of
each number. If the XOR is equal to 1, that means only one
of the inputs is negative, meaning that the sign bit should be
negative. If the XOR is 0, we branch to “positive” which
restores the stack and jumps back to the caller. If the code
does not jump to positive, twos complement 64 bit is called
on hi and lo and then the stack is restored and returned back
to the caller.
CS47 6
4) Division implementation
i) Division_au_logical
Division_au_logical obtains the twos complement of the
two inputs if they are below 0. Then the method jumps to
div_unsigned.
ii) div_unsigned
Div_unsigned begins by setting up the proper arguments
as variables. A counter, $s7, is initialized to 0. $s0, which
holds the Quotient, is set to $s1. $a1, which holds the dvsr,
is set to $s2. And finally $s3, which is the remainder, is set
to 0.
iii) left_shift_and_extract
In left_shift_and_extract, the remainder is shifted left by
1 bit. Then the 31st bit of the quotient ($s1) is put into the
0th bit position of the remainder ($s3). The quotient is then
shifted left by one bit. Next, an intermediate value (S) is
calculated by subtracting the dvsr from the remainder. I
was not able to call the actual sub_logical routine since that
will always jump back to the caller code, so I copy and
pasted by sub_logical code into this method. The difference
is taken and is stored into S ($v0). Next, we check if S is 0,
basically if the Dvsr is greater than the remainder. If it is
less than 0, we jump to increment counter. If S is not
greater than 0 , we set R to equal S and make the 0th bit of Q
a 1. Then we jump to increment counter and do the same
checking.
iv) increment_counter
Increment_counter increments the counter by 1 and
compares it to 32. If the counter equals 32, we jump to
end_division, or else we go back to left_shift_and_extract.
v) end_division
End_division takes care of adding the proper sign to the
quotient and remainder. The 31st bits of the original inputs
are extracted and XOR is called on both of them. If the
XOR is 1, that means only one number is negative, meaning
that the sign bit should be negative. If the XOR’d answer is
equal to 0, we branch to positive_div. If it equals 1, we
figure out the correct signs to put on the remainder and the
quotient by using various twos_complements calls.
CS47 7
IV. TESTING
Another class, called “proj_alu_normal” is created. This is
also an arithmetic calculator, but does not use logic to
perform the operations. Instead, it uses MIPS inbuilt
arithmetic operations such as “add”, “sub”, “mul”, and
“div”.
A) Implementation
1) addition_au_normal
Addition_au_normal calls the MIPS add instruction to add
the two inputs. Just like in au_logical, the arguments are
passed through the method in $a0 and $a1, and the result is
stored in $v0.
2) subtraction_au_normal
Subtraction_au_normal calls the MIPS subtraction
instruction to subtract the two inputs. Similarly to
addition_au_normal, the arguments are passed through the
method in $a0 and $a1, and the result is stored in $v0.
3) Multiplication_au_normal
Multiplication_au_normal calls the MIPS “mul” instruction
and stores the result in $v0. The hi value is then moved into
the $v1 register. V. CONCLUSION
This project, although a tough and tedious one, was made
4) Division_au_normal to implement a calculator using logical operations only.
Division_au_normal calls the MIPS “div” instruction on It was basically writing software that simulates the
$a0 and $a1, which are the two inputs. The hi value hardware, which performs these logical operations. The
contains the remainder and the lo value contains the program was written in the MIPS assembly language and
quotient. The remainder is moved into $v1 and the quotient tested using a tester file that Professor Patra provided.
is moved into $v0.
B) Proj-auto-test
Professor Patra wrote assembly code which tests that the
calculator works properly. The code provides sample inputs
and does the operations using the au_normal and au_logical.
The file see’s if the au_normal results match the au_logical
results. The following is a picture of the proj_auto_test