sub

sub

RISC-V Assembly Reference

lyszt.net covers sub and other RISC-V instructions in more detail.

Encoding format

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

Description

sub subtracts the value in one register from another and writes the result into a third. It works on registers, the small numbered storage slots inside the processor that each hold one 32-bit number.

The form of sub is shown below, and the result is rd = rs1 - rs2. rd is the destination register, where the answer goes. rs1 and rs2 are the source registers. The order matters, and reversing it is a common slip for beginners.

sub rd, rs1, rs2

The next line computes t0 minus t1. The left source is the value that is subtracted from.

sub t2, t0, t1

There is no subi instruction for subtracting a constant. addi accepts negative constants, so subtracting a fixed number means adding its negative. The next line lowers t0 by one.

addi t0, t0, -1

RISC-V has a special register named zero that always holds the value 0. Subtracting a number from zero flips its sign, so the next line puts the negative of t1 into t0. The neg instruction is shorthand for this.

sub t0, zero, t1

The RISC-V manual defines sub as the subtraction of rs2 from rs1. Overflow is ignored and only the low XLEN bits of the result are written to rd, where XLEN is the register width in bits, which is 32 here. The manual also lists register x0, which this simulator names zero, as hardwired to a value with all bits 0.

In the example, 10 minus 4 leaves 6 in t2. Swapping the two sources gives -6, which the processor stores in its own scheme for negative numbers.

Example

li t0, 10
li t1, 4
sub t2, t0, t1   # t2 = 6