Doing math
All calculations take place between registers. An arithmetic instruction names the destination first, followed by the two sources it reads: means dest = src1 + src2.
add places t0 + t1 in t2.
t0 and t1, always in that order. They enter the same shape regardless of which operation is running: add, subtract, multiply, divide, or remainder. Two values go in, one operation happens, and one result comes out into t2 on the right. names t2 first because that is where the result lands, which matches the one ordering rule that every arithmetic instruction in this lesson follows.Adding and subtracting
takes the numbers held in two registers and stores their sum in a third. does the same for subtraction: computes t0 - t1. Both instructions read from registers only.
add t2, t0, t1 # t2 = t0 + t1sub t2, t0, t1 # t2 = t0 - t1
One thing to know: a register holds only 32 bits, so there is a ceiling. If a result is too big to fit, no error is raised. The value quietly wraps around to very low numbers and execution continues. Everyday values will not reach this limit, but the ceiling is worth knowing about.
To use a fixed number in place of a second register, add the letter i, which stands for immediate: adds the constant 1. There is no subi, so to subtract a constant you add a negative one: .
Multiplying and dividing
multiplies two registers. divides them as whole numbers and discards the fraction, so 7 / 2 yields 3. gives the remainder, so 7 % 2 yields 1. Division never causes a crash. Dividing by zero returns -1.
mul t2, t0, t1 # t2 = t0 * t1div t2, t0, t1 # t2 = t0 / t1 (integer)rem t2, t0, t1 # t2 = t0 % t1 (remainder)
Putting it together
li t0, 7li t1, 5add t1, t0, t1 # t1 = 7 + 5 = 12mv a0, t1 # the print service reads a0li a7, 1ecallli a7, 10ecall
loads 7 into t0. loads 5 into t1. adds them and writes 12 into t1. copies the result into a0, because the print service always reads its value from a0. Then selects the print-integer service and runs it. Finally, and end the program.
Bonus: multiplying with shifts
When the factor is a power of two, a faster method than exists. (shift left logical) moves a register's bits to the left, and every position you shift doubles the value: shift by 1 to multiply by 2, by 2 for 4, by 3 for 8. Shifting costs less than multiplying, so compilers use it often.
li t0, 5 # start with 5# shift left by 3 bits (5 * 2^3 = 5 * 8)sll a0, t0, 3 # a0 = 40li a7, 1 # print integerecallli a7, 10ecall
puts 5 in t0. shifts its bits three places left. Each place doubles the value, so 5 doubles three times (5, 10, 20, 40), giving 40 in a0. The rest follows the print pattern from before. Try changing the 3 to a 1 or a 2 and predict the result before you run it.
5 shifted left 0 bits stays 5.
