Skip to content

RISC-V Assembler Cheat Sheet

A thorough reference to 32-bit RISC-V instructions, registers, and fundamental concepts. This guide is intended for software developers working with the RISC-V assembly language and includes grouped instructions by purpose, common pseudoinstructions, and usage examples.

Table of Contents

  1. Arithmetic Instructions
  2. Bitwise Logic Instructions
  3. Shift Instructions
  4. Load Immediate Instructions
  5. Load and Store Instructions
  6. Jump and Function Instructions
  7. Branch Instructions
  8. Set Instructions
  9. Counter Instructions
  10. Miscellaneous Instructions
  11. Instruction Terminology
  12. RV32 ABI Registers
  13. RISC-V Concepts
  14. Usage Examples

Arithmetic Instructions

Arithmetic operations perform basic mathematical computations.

Instruction Description Usage Result Guide
add Add add rd, rs1, rs2 rd = rs1 + rs2 Arithmetic
addi Add Immediate addi rd, rs1, imm rd = rs1 + imm Arithmetic
neg Negate (pseudoinstruction) neg rd, rs2 rd = -rs2 Arithmetic
sub Subtract sub rd, rs1, rs2 rd = rs1 - rs2 Arithmetic
mul Multiply mul rd, rs1, rs2 rd = (rs1 * rs2)[31:0] Multiply
mulh Multiply High mulh rd, rs1, rs2 rd = (rs1 * rs2)[63:32] Multiply
mulhu Multiply High Unsigned mulhu rd, rs1, rs2 rd = (rs1 * rs2)[63:32] Multiply
mulhsu Multiply High Signed Unsigned mulhsu rd, rs1, rs2 rd = (rs1 * rs2)[63:32] Multiply
div Divide div rd, rs1, rs2 rd = rs1 / rs2 Divide
rem Remainder rem rd, rs1, rs2 rd = rs1 % rs2 Divide

Notes: - Use addi for subtracting with an immediate value: addi rd, rs1, -imm - Multiply and divide instructions require the M extension.

Example:

addi t0, t1, 10      # t0 = t1 + 10
sub t2, t0, t1       # t2 = t0 - t1
mul t3, t2, t1       # t3 = t2 * t1

Bitwise Logic Instructions

Perform logical operations on binary data.

Instruction Description Usage Result Guide
and Logical AND and rd, rs1, rs2 rd = rs1 & rs2 Logical
andi AND Immediate andi rd, rs1, imm rd = rs1 & imm Logical
not Logical NOT (pseudoinstruction) not rd, rs1 rd = ~rs1 Logical
or Logical OR or rd, rs1, rs2 rd = rs1 | rs2 Logical
ori OR Immediate ori rd, rs1, imm rd = rs1 | imm Logical
xor Logical XOR xor rd, rs1, rs2 rd = rs1 ^ rs2 Logical
xori XOR Immediate xori rd, rs1, imm rd = rs1 ^ imm Logical

Example:

and t0, t1, t2       # t0 = t1 & t2
ori t3, t0, 0xFF     # t3 = t0 | 0xFF
not t4, t3           # t4 = ~t3

Shift Instructions

Handle bitwise shifting operations.

Instruction Description Usage Result Guide
sll Shift Left Logical sll rd, rs1, rs2 rd = rs1 << rs2 Shift
slli Shift Left Logical Immediate slli rd, rs1, imm rd = rs1 << imm Shift
srl Shift Right Logical srl rd, rs1, rs2 rd = rs1 >> rs2 Shift
srli Shift Right Logical Immediate srli rd, rs1, imm rd = rs1 >> imm Shift
sra Shift Right Arithmetic sra rd, rs1, rs2 rd = rs1 >>> rs2 Shift
srai Shift Right Arithmetic Immediate srai rd, rs1, imm rd = rs1 >>> imm Shift

Example:

slli t0, t1, 2       # t0 = t1 << 2
srli t2, t0, 1       # t2 = t0 >> 1
sra t3, t2, t1       # t3 = t2 >>> t1

Load Immediate Instructions

Load immediate values into registers.

Instruction Description Usage Result Guide
li Load Immediate (pseudoinstruction) li rd, imm rd = imm Arithmetic
lui Load Upper Immediate lui rd, imm rd = imm << 12 Arithmetic
auipc Add Upper Immediate to PC auipc rd, imm rd = pc + (imm << 12) Branch

Example:

li t0, 100           # t0 = 100
lui t1, 0x1F         # t1 = 0x1F000
auipc t2, 0x10       # t2 = pc + 0x10000

Load and Store Instructions

Manage data movement between registers and memory.

Instruction Description Usage Result Guide
lw Load Word lw rd, imm(rs1) rd = mem[rs1 + imm] Load
lh Load Half lh rd, imm(rs1) rd = mem[rs1 + imm][0:15] Load
lhu Load Half Unsigned lhu rd, imm(rs1) rd = mem[rs1 + imm][0:15] Load
lb Load Byte lb rd, imm(rs1) rd = mem[rs1 + imm][0:7] Load
lbu Load Byte Unsigned lbu rd, imm(rs1) rd = mem[rs1 + imm][0:7] Load
la Load Symbol Address (pseudoinstruction) la rd, symbol rd = &symbol Load
sw Store Word sw rs2, imm(rs1) mem[rs1 + imm] = rs2 Store
sh Store Half sh rs2, imm(rs1) mem[rs1 + imm][0:15] = rs2 Store
sb Store Byte sb rs2, imm(rs1) mem[rs1 + imm][0:7] = rs2 Store

Example:

lw t0, 0(sp)         # t0 = mem[sp + 0]
sw t1, 4(sp)         # mem[sp + 4] = t1
la t2, data_label    # t2 = address of data_label

Jump and Function Instructions

Control the flow of the program through jumps and function calls.

Instruction Description Usage Result Guide
j Jump (pseudoinstruction) j imm pc += imm Jump
jal Jump and Link jal rd, imm rd = pc + 4; pc += imm Jump
jalr Jump and Link Register jalr rd, rs1, imm rd = pc + 4; pc = rs1 + imm Jump
call Call Function (pseudoinstruction) call symbol ra = pc + 4; pc = &symbol Function
ret Return from Function (pseudoinstruction) ret pc = ra Function

Notes: - Labels can be used in place of immediate values for jump instructions.

Example:

jal ra, function_label    # Jump to function_label and store return address in ra
call main                 # Call the main function
ret                       # Return from the current function

Branch Instructions

Conditional branching based on comparisons.

Instruction Description Usage Result Guide
beq Branch Equal beq rs1, rs2, imm if(rs1 == rs2) pc += imm Branch
beqz Branch Equal Zero (pseudoinstruction) beqz rs1, imm if(rs1 == 0) pc += imm Branch
bne Branch Not Equal bne rs1, rs2, imm if(rs1 ≠ rs2) pc += imm Branch
bnez Branch Not Equal Zero (pseudoinstruction) bnez rs1, imm if(rs1 ≠ 0) pc += imm Branch
blt Branch Less Than blt rs1, rs2, imm if(rs1 < rs2) pc += imm Branch
bltu Branch Less Than Unsigned bltu rs1, rs2, imm if(rs1 < rs2) pc += imm Branch
bltz Branch Less Than Zero (pseudoinstruction) bltz rs1, imm if(rs1 < 0) pc += imm Branch
bgt Branch Greater Than (pseudoinstruction) bgt rs1, rs2, imm if(rs1 > rs2) pc += imm Branch
bgtu Branch Greater Than Unsigned (pseudoinstruction) bgtu rs1, rs2, imm if(rs1 > rs2) pc += imm Branch
bgtz Branch Greater Than Zero (pseudoinstruction) bgtz rs1, imm if(rs1 > 0) pc += imm Branch
ble Branch Less or Equal (pseudoinstruction) ble rs1, rs2, imm if(rs1 ≤ rs2) pc += imm Branch
bleu Branch Less or Equal Unsigned (pseudoinstruction) bleu rs1, rs2, imm if(rs1 ≤ rs2) pc += imm Branch
blez Branch Less or Equal Zero (pseudoinstruction) blez rs1, imm if(rs1 ≤ 0) pc += imm Branch
bge Branch Greater or Equal bge rs1, rs2, imm if(rs1 ≥ rs2) pc += imm Branch
bgeu Branch Greater or Equal Unsigned bgeu rs1, rs2, imm if(rs1 ≥ rs2) pc += imm Branch
bgez Branch Greater or Equal Zero (pseudoinstruction) bgez rs1, imm if(rs1 ≥ 0) pc += imm Branch

Notes: - Labels can be used in place of immediate values for branch instructions.

Example:

beq t0, t1, equal_label    # If t0 == t1, jump to equal_label
bnez t2, not_zero_label    # If t2 != 0, jump to not_zero_label
blt t3, t4, less_than_label # If t3 < t4, jump to less_than_label

Set Instructions

Set register values based on comparisons.

Instruction Description Usage Result Guide
slt Set Less Than slt rd, rs1, rs2 rd = (rs1 < rs2) Set
slti Set Less Than Immediate slti rd, rs1, imm rd = (rs1 < imm) Set
sltu Set Less Than Unsigned sltu rd, rs1, rs2 rd = (rs1 < rs2) Set
sltiu Set Less Than Immediate Unsigned sltiu rd, rs1, imm rd = (rs1 < imm) Set
seqz Set Equal Zero (pseudoinstruction) seqz rd, rs1 rd = (rs1 == 0) Set
snez Set Not Equal Zero (pseudoinstruction) snez rd, rs1 rd = (rs1 ≠ 0) Set
sltz Set Less Than Zero (pseudoinstruction) sltz rd, rs1 rd = (rs1 < 0) Set
sgtz Set Greater Than Zero (pseudoinstruction) sgtz rd, rs1 rd = (rs1 > 0) Set

Example:

slt t0, t1, t2        # t0 = (t1 < t2)
slti t3, t0, 5        # t3 = (t0 < 5)
seqz t4, t3           # t4 = (t3 == 0)

Counter Instructions

Access CPU cycle and instruction counters. Note: These instructions require the Zicntr and Zicsr extensions and are not yet available in all implementations.

Instruction Description Usage Result Guide
rdcycle CPU Cycle Count (pseudoinstruction) rdcycle rd rd = csr_cycle[31:0] Not Available
rdcycleh CPU Cycle Count High (pseudoinstruction) rdcycleh rd rd = csr_cycle[63:32] Not Available
rdtime Current Time (pseudoinstruction) rdtime rd rd = csr_time[31:0] Not Available
rdtimeh Current Time High (pseudoinstruction) rdtimeh rd rd = csr_time[63:32] Not Available
rdinstret CPU Instructions Retired (pseudoinstruction) rdinstret rd rd = csr_instret[31:0] Not Available
rdinstreth CPU Instructions Retired High (pseudoinstruction) rdinstreth rd rd = csr_instret[63:32] Not Available

Miscellaneous Instructions

Additional instructions for various purposes.

Instruction Description Usage Result Guide
ebreak Environment Break (Debugger Call) ebreak - Not Available
ecall Environment Call (OS Function) ecall - Not Available
fence I/O Ordering fence - Not Available
mv Copy Register (pseudoinstruction) mv rd, rs1 rd = rs1 Arithmetic
nop No Operation (pseudoinstruction) nop - Arithmetic

Notes: - The fence instruction requires the Zifencei extension.

Example:

mv t0, t1            # t0 = t1
nop                  # No operation
ecall                # Environment call

Instruction Terminology

Understanding the terminology used in RISC-V assembly instructions.

Term Description
imm Immediate value (normally sign-extended)
mem Memory
(p) Pseudoinstruction
pc Program counter
pc+4 Next instruction on RV32
ra Return address register (x1)
rd Destination register
rs1 First source register
rs2 Second source register
symbol Symbol (may be a label in assembly)

RV32 ABI Registers

Overview of the ABI (Application Binary Interface) registers for RV32.

ABI Name Register Description Preserved
zero x0 Always 0 (zero) N/A
ra x1 Return address No
sp x2 Stack pointer Yes
gp x3 Global pointer* N/A
tp x4 Thread pointer* N/A
t0 x5 Temporary No
t1 x6 Temporary No
t2 x7 Temporary No
fp (s0) x8 Frame pointer† Yes
s1 x9 Saved register Yes
a0 x10 Function argument‡ No
a1 x11 Function argument‡ No
a2 x12 Function argument No
a3 x13 Function argument No
a4 x14 Function argument No
a5 x15 Function argument No
a6 x16 Function argument No
a7 x17 Function argument No
s2 x18 Saved register Yes
s3 x19 Saved register Yes
s4 x20 Saved register Yes
s5 x21 Saved register Yes
s6 x22 Saved register Yes
s7 x23 Saved register Yes
s8 x24 Saved register Yes
s9 x25 Saved register Yes
s10 x26 Saved register Yes
s11 x27 Saved register Yes
t3 x28 Temporary No
t4 x29 Temporary No
t5 x30 Temporary No
t6 x31 Temporary No

Notes: - * Let the compiler/linker use the global gp and thread tp pointers; ignore them in your own code. - † The frame pointer fp supports local variables but can be used as a regular saved register. - ‡ Argument registers a0 and a1 also handle the function return value.


RISC-V Concepts

Key concepts to understand when working with RISC-V assembly:

  • Extensions: RISC-V is modular, allowing for different extensions (e.g., M for Multiply/Divide, A for Atomic, etc.) to add functionality.
  • Base Instruction Set: This cheat sheet focuses on the base integer instruction set (RV32I).
  • Pseudoinstructions: These are simplified instructions that are translated into one or more actual RISC-V instructions by the assembler.

Usage Examples

Below are examples demonstrating how to use various RISC-V instructions in assembly code.

Example 1: Simple Arithmetic Operations

.section .text
.globl main

main:
    li t0, 10          # Load immediate 10 into t0
    li t1, 20          # Load immediate 20 into t1
    add t2, t0, t1     # t2 = t0 + t1 (30)
    sub t3, t1, t0     # t3 = t1 - t0 (10)
    mul t4, t2, t3     # t4 = t2 * t3 (300)
    ecall              # Exit program

Example 2: Branching Based on Comparison

.section .text
.globl main

main:
    li t0, 5           # t0 = 5
    li t1, 10          # t1 = 10
    blt t0, t1, less_than_label  # If t0 < t1, jump to less_than_label
    j end_label        # Else, jump to end_label

less_than_label:
    li a0, 1           # Set a0 to 1 (indicating true)
    j end_label

end_label:
    li a0, 0           # Set a0 to 0 (indicating false)
    ecall              # Exit program

Example 3: Function Call and Return

.section .text
.globl main

main:
    jal ra, function_label  # Jump to function_label and save return address
    li a0, 0               # Set return value to 0
    ecall                  # Exit program

function_label:
    addi sp, sp, -16       # Allocate stack space
    sw ra, 12(sp)          # Save return address
    li t0, 42              # Perform some operations
    lw ra, 12(sp)          # Restore return address
    addi sp, sp, 16        # Deallocate stack space
    jalr ra, 0(ra)         # Return to caller

Additional Resources


This cheat sheet covers the base integer instruction set (RV32I) and some standard extensions. Make sure to consult the official RISC-V documentation for comprehensive information and updates.