RISC-V Assembly Code Examples
Learning RISC-V Assembly code trough simple examples and exercises
--
A lot of RISC-V example code jumps straight into fairly complex code examples. I intend to start slow do some very simple examples.
For a proper introduction to things such as registers, conditional branching and assembly code format, I advice reading: RISC-V Assembly for Beginners.
That is an overview story, but does not contain that many examples. As with the first article we will use the online Cornell University RISC-V interpreter.
When working through the code examples, you could print out this RISC-V reference sheet to help you: James Zhu’s RISC-V Reference.
The most important instructions are probably:
ADDI rd, zero, immediate
, to load a value (immediate
) into registerrd
.LW rd, offset(rs1)
to load content at memory locationoffset + rs1
into registerrd
.SW rd, offset(rs1)
store content ofrd
register at memory locationoffset + rs1
.ADD rd, rs1, rs2
to content of two registers and store value in destination registerrd
.- The branch instructions
BEQ
,BNE
,BLT
. Read previous story for more details.
Input Doubler
Let us begin with a really simple example. You are writing a function which doubles the its input. If you read my previous intro: RISC-V Assembly for Beginners.
You should know that on RISC-V functions get their inputs in registers a0
, a1
, up to a7
. These are just aliases for registers starting at x10
.
Jot down a solution before looking at my solution below:
doubler:
ADD a0, a0, a0
To test this put an initial value in register a0
before running the code in the simulator. If it works, then a0
should be doubled. Functions should return their result in a0
so this is correct way of doing it.
If this was real function which got called from somewhere else, we would need this line at the end to return from function:
JALR zero, ra, 0