Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1Learning Outcomes

2add and sub Instructions

Generally, assembly instructions have a very rigid format. Consider arithmetic and logic instructions like addition (add), bitwise AND (and), etc., which operate on two registers and store the result in a third register. These instructions always follow the same rigid syntax shown in Figure 1:

"TODO"

Figure 1:R-Type instructions (arithmetic and logic involving two source registers).

The fields are separated by spaces[1], in order:

The full set of instructions that follow the format in Figure 1 are located on the RISC-V green card. For now, we focus on two instructions in Table 1:

Table 1:The add and sub instructions.

InstructionNameDescription[2]
add rd rs1 rs2ADDR[rd] = R[rs1] + R[rs2]
sub rd rs1 rs2SUBtractR[rd] = R[rs1] - R[rs2]

The addition command in assembly is simply add, which is easy to remember. The RV32I instruction

add x1, x2, x3

is equivalent to the C statement a = b + c; for 32-bit integers[3] a, b, and c, where each variable corresponds to a value stored in a register. In Figure 2, the variable a is in register x1, variable b is in register x2, and variable c is in x3.

"TODO"

Figure 2:Addition instruction add in RISC-V and C.

Subtraction works almost the same way, using the operation sub. If you want to subtract the values in x4 and x5 and store the result in x3, you would write the below, which is equivalent to the C integer arithmetic statement d = e - f; (Figure 3).

sub x3, x4, x5
"TODO"

Figure 3:Subtraction instruction sub in RISC-V and C.

2.1RISC Arithmetic: Examples

As mentioned earlier, a single line of C may translate into several lines of RISC-V. Consider the C integer arithmetic statement:

a = b + c + d - e;

Suppose that variables a, b, c, d, and e mapped to registers x10, x1, x2, x3, and x4, respectively. We can use x10 as a running sum to compute the correct value of a after three instructions:

add x10  x1 x2   # a_temp = b + c
add x10 x10 x3   # a_temp = a_temp + d
sub x10 x10 x4   # a = a_temp - e

3Immediates

Immediates are numerical constants in RISC-V. Immediates are called as such because their bit patterns are directly encoded into the machine instruction—thus their values are “immediately” available to the computer.

Immediates appear often in code; hence, they have separate instructions (Figure 5).

"TODO"

Figure 5:Arithmetic and Logical I-Type instructions involving one source register and one immediate.

Like before, fields are separated by spaces[1], in order:

The full set of instructions that follow the format in Figure 5 are located on the RISC-V green card.

3.1addi instruction

Let’s discuss the Add Immediate instruction (Table 2).

Table 2:The addi instruction.

InstructionNameDescription[2]
addi rd rs1 immADD ImmediateR[rd] = R[rs1] + imm

The RV32I instruction

addi x3, x4, 10

is equivalent to the C statement f = g + 10;, where f and g are 32-bit integers (Figure 6).

"TODO"

Figure 6:Add immediate instruction in RISC-V and C.

4Using x0 to reduce our instruction set

We have previously discussed the zero register x0. Hardwiring register x0 to the value zero proves extremely useful for reusing add and addi for very common C operations. Two toy examples are shown in Figure 8 and Figure 9:

"TODO"

Figure 8:To assign the C integer variable f to the value of another integer variable g, we could use add with x0 as a source operand (though we don’t in practice[4]).

"TODO"

Figure 9:To assign the variable f to a numeric constant, use addi with x0 as the source register operand.

5Pseudoinstructions

We have just seen several cases where common C statements translate into other instructions in our reduced instruction set architecture. While this is fine and dandy for designing architecture, compilers (and you, as a human assembly instruction-writer) will find it useful to use pseudoinstructions.

Pseudoinstructions are convenient instructions in RISC-V. Pseudoinstructions help compilers more directly translate higher-level language code into assembly instructions (really!), but by themselves they are not real instructions.

Consider two examples below (and see the full set in the RISC-V green card).

Table 3:The subset pseudoinstructions.

PseudoinstructionNameDescriptionTranslation
mv rd rs1MoVeR[rd] = R[rs1]addi rd rs1 0[4]
li rd immLoad ImmediateR[rd] = immaddi rd x0 imm[5]
nopNo OPerationdo nothing[6]addi x0 x0 0

When assembling to machine instructions, the assembler replaces pseudoinstructions with their real instruction counterpart.

Footnotes
  1. Stylistically, assembly instructions can include commas. In RISC-V, commas are not needed. We stick to a space-only convention in this course.

  2. We won’t expect you to know Verilog in this course, but the syntax is useful. R[rs1] means the data in register rs1.

  3. You will see later that signed and unsigned addition and subtraction are implemented with the same hardware circuit.

  4. Why addi with immediate 0 and not add with x0 (as in Figure 8)? See the ASM manual on GitHub.

  5. This description is incomplete given the range of imm in addi. See the green-card and future sections for the full translation of load immediates.

  6. We will see later how a “no-op” instruction can improve hardware performance (really).