slt
slt
rd, rs1, rs2
rd = (rs1 < rs2) ? 1 : 0
R
31–25funct7
24–20rs2
19–15rs1
14–12funct3
11–7rd
6–0opcode
I
31–20imm[11:0]
19–15rs1
14–12funct3
11–7rd
6–0opcode
S
31–25imm[11:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:0]
6–0opcode
B
31–25imm[12,10:5]
24–20rs2
19–15rs1
14–12funct3
11–7imm[4:1,11]
6–0opcode
U
31–12imm[31:12]
11–7rd
6–0opcode
J
31–12imm[20,10:1,11,19:12]
11–7rd
6–0opcode

slt compares two numbers and records the answer as a 1 or a 0. Its name is short for set less than. The form slt rd, rs1, rs2 asks the question is rs1 less than rs2 — if yes, it writes 1 into destination register rd; if no, it writes 0.

This is worth pausing on, because it introduces a key idea. There are two ways to use a comparison. One is to immediately jump somewhere based on it (that is what the branch instructions do). The other is to *store* the yes/no answer as a number — 1 for true, 0 for false — and keep working with it. slt does the second. That stored 1-or-0 is how assembly represents a true/false value, and it can then be added, masked, or combined like any other number.

The comparison treats the values as signed, meaning they may be negative: -1 counts as less than 0. (A sibling instruction, sltu, treats them as unsigned instead, which changes the answer for large or negative-looking values.)

Notice there is no set greater than instruction — none is needed, because you can just swap the two operands: to test whether a is greater than b, ask whether b is less than a. The example compares 3 and 9; since 3 is indeed less than 9, t2 is set to 1.

li t0, 3
li t1, 9
slt t2, t0, t1   # t2 = 1