Maximum and unsigned distance

This program compares two signed numbers. It leaves their maximum in $t2 and the unsigned distance between them in $t4. Step through it once and watch the pc: only one of the two paths runs.

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

    slt $t3, $t0, $t1   # $t3 = 1 when signed a < signed b
    beqz $t3, a_is_at_least_b

    move $t2, $t1       # maximum = b
    subu $t4, $t1, $t0  # distance = b - a
    j done

a_is_at_least_b:
    move $t2, $t0       # maximum = a
    subu $t4, $t0, $t1  # distance = a - b

done:
    li $v0, 10
    syscall

slt performs a signed comparison. It writes 1 to $t3 when a < b, and 0 otherwise. beqz then tests only whether $t3 is zero; a zero test has no signed or unsigned interpretation. When $t3 is 0, execution jumps to a_is_at_least_b, which also handles equality.

When a < b, execution continues into the first path: it copies b to $t2 and calculates b - a. Its j done skips the other path. When a >= b, the branch goes to a_is_at_least_b, where the program copies a and calculates a - b. In either case, execution reaches done after just one path.

The signed comparison tells us which number is larger. Subtracting the smaller number from the larger one gives their distance. Both paths use subu, which keeps the 32-bit subtraction result without a signed-overflow exception. Read $t4 as an unsigned number: that gives the distance even when it is too large to fit in a signed 32-bit number.

Run the program as written. At syscall, $t2 should be 64 and $t4 should be 27. The register panel shows hexadecimal by default, so these appear as 00000040 and 0000001B. To practise both routes, replace the two li values with each row below. Predict the route and results before running, then check $t2 and $t4 in the register panel. The table gives the results in decimal.

abRoute$t2 maximum$t4 unsigned distance
3764a < b: first path6427
9964a >= b: a_is_at_least_b9935
6464a >= b: a_is_at_least_b640
-9-2a < b: first path-27
What if the distance is too large for a signed number?

Try a = -2147483648 and b = 2147483647. Their distance is 4294967295, which fits in an unsigned 32-bit number. subu leaves FFFFFFFF in $t4. Those same bits mean -1 if you read them as a signed number, so use the unsigned reading for the distance.

Now write the selection yourself. The test supplies signed a in $t0 and b in $t1. Leave their signed maximum in $t2, and keep both inputs unchanged. Use slt to compare them, beqz to choose the a >= b path, and j done after the a < b path so only one value is copied. For a = 7 and b = 4, what should $t2 contain? Write your instructions in the exercise editor, then select Test. Once it passes, select Open in editor and use Testcases to try a = 4, b = 7 and a = -9, b = -2. Update both the starting $t0/$t1 values and the expected $t0/$t1/$t2 values. The two expected maxima are 7 and -2, respectively.

.text
main:
    # $t0 and $t1 are supplied by the test.
    # Leave their signed maximum in $t2.

    li $v0, 10
    syscall
Show solution
.text
main:
    slt $t3, $t0, $t1
    beqz $t3, a_is_at_least_b

    move $t2, $t1
    j done

a_is_at_least_b:
    move $t2, $t0

done:
    li $v0, 10
    syscall