The bigger of two numbers

Two numbers sit in registers, and the program leaves the larger of them in t2 and the distance between them in t4. It is the first program here where some instructions get skipped, so step through it rather than running it and watch which ones the arrow visits.

.text
main:
    li t0, 37               # a = 37
    li t1, 64               # b = 64

    blt t1, t0, a_is_bigger # if b is below a, a is the answer
    mv t2, t1               # otherwise b is
    j done
a_is_bigger:
    mv t2, t0
done:

    slt t3, t0, t1          # the same question, answered as a number

    sub t4, t0, t1          # the distance, which may come out negative
    bgez t4, positive       # if it did not, it is already the answer
    sub t4, zero, t4        # otherwise flip its sign
positive:

blt t1, t0, a_is_bigger reads as: if t1 is less than t0, carry on from the label. Both numbers being compared are named right there in the instruction, and the jump either happens or it does not. Nothing is left behind for a later instruction to read.

slt t3, t0, t1 asks the same question and answers it differently. Instead of jumping it writes 1 or 0 into t3, so you get the comparison as a value you can keep, add to something, or test later. Reach for the branch when the next thing to do is choose between two pieces of code, and for slt when you want the answer itself.

The j done is the part that is easy to leave out. Two pieces of code, only one of them allowed to run, so the first one has to jump over the second. Delete that line and the program runs straight into a_is_bigger and overwrites the answer it just worked out, which is a good thing to see once on purpose.

The second half does not need a fresh comparison value. sub t4, t0, t1 has already produced the difference, and bgez t4, positive looks at that same register: if the subtraction came out at zero or above, the answer is already right and the next line is skipped. bgez is a convenient pseudo-instruction; the assembler expands bgez t4, positive to the real two-register branch bge t4, zero, positive. sub t4, zero, t4 flips the sign, since 0 minus a number is its negative, and neg t4, t4 is the shorter name for that subtraction.

Both blt and the bge behind bgez use signed ordering, which is what a difference that may go below zero needs. There is a bltu next to blt that reads both registers as unsigned counts, and it would treat a negative number as a very large positive one.

Your turn: choose the larger number and find the distance

The test runner supplies two small signed numbers in t0 and t1; their difference always fits in a signed 32-bit register. Write the branch-based if/else that leaves the larger number in t2. Then leave the nonnegative distance between the inputs in t4. Do not replace the starting values in t0 or t1.

.text
main:
    # choose the larger value for t2
    # find the nonnegative distance for t4
Show solution
.text
main:
    blt t1, t0, first_is_bigger
    mv  t2, t1
    j   have_bigger
first_is_bigger:
    mv  t2, t0
have_bigger:
    sub t4, t0, t1
    bge t4, zero, done
    sub t4, zero, t4
done: