RISC-V uses byte-addressable memory, meaning each individual byte in memory has a unique address. This is in contrast to word-addressable architectures where the smallest addressable unit is an entire word. Consequently, consecutive bytes have consecutive addresses, and a 32-bit word spans four addressable byte locations.
In RISC-V, comments are started with a hash (#) symbol, e.g.:
# This is a commentadd a, b, c
Labels
Labels name instruction addresses in assembly code. They are written as identifiers followed by a colon (:) and are used as branch and jump targets.
loop: addi t0, t0, -1 bne t0, zero, loop
Function Calling Convention
Caller:
passes arguments to callee
jumps to callee
Callee:
performs the function
returns result to caller
jumps to point of call
must not overwrite registers or memory needed by caller
Preserved values are the parts of machine state that must survive across a function call. The callee is responsible for saving and restoring them if it modifies them.
Space below the current stack pointer may be used for new stack frames.
Storing Register Values on the Stack
The following example saves one register on the stack, uses it as a temporary variable, and restores it before returning:
addi sp, sp, -4 # make space on stack for one wordsw s0, 0(sp) # save s0 on stackaddi s0, a0, 1 # use s0 as a temporary variableadd a0, s0, zero # put return value in a0lw s0, 0(sp) # restore s0 from stackaddi sp, sp, 4 # deallocate stack spacejr ra # return to caller
Instructions
Definition
Instruction (RISC-V)
An instruction is a machine-level operation encoded as a binaryword.
In the base RISC-V ISA, standard instructions are 32 bits wide. The compressed extension adds 16-bit compressed instructions.
A compressed instruction is a 16-bit RISC-V instruction encoding.
It is part of the compressed extension and represents a common operation in a shorter form than the standard 32-bit instruction. Compressed mnemonics are commonly prefixed with c..
An exception is an event detected by the processor that transfers control to an exception handler.
In RISC-V, the handler address is stored in mtvec. The handler uses mcause to identify the cause of the exception, may save registers in mscratch, and can use mepc to resume execution after handling.
We want to translate the following C code to RISC-V:
int array[5];array[0] = array[0] * 2;array[1] = array[1] * 2;
Solution: First, we choose 0x123BF780 (arbitrary) as base address. Given that we can’t pass 32-bit immediate values, we have to do the trick from example 1:
# s0 = array base addresslui s0, 0x123B4 # 0x123B4 in the upper 20 bits of s0addi s0, s0, 0x780 # s0 = 0x123Bf780
Next, we can load the value at index 0 to t1 (lw) and double it by shifting it by one bit (slli; i.e. doubling it) and writing the result back (sw):