Smallest program
To get started with writing RISC-V assembly, we need a few things:
- A
textsection, to hold the actual program code. - A
mainlabel, to indicate where the program starts. - An
ecallinstruction, to terminate the program (or an infinite halt).
The smallest RISC-V code
Section titled “The smallest RISC-V code”This program here will compile just fine and run without errors:
.textmain: li x17, 10 ecallLet’s break it down.
The .text section
Section titled “The .text section”In the Von Neumann architecture, the code for a program is stored in memory, right alongside the data it is using.
To tell the assembler that the following lines are code and not data
we use the .text directive:
.textThis has to go before any code instructions, or we’ll get an error:
[E18] Error: Can't use instruction statements while in section None ╭─[ assembly:2:5 ] 2 │ li x17, 10 │ ──┬── │ ╰──── This statement can't be used in the current section │ Help: Consider changing the section to Text, using .text │ Note: No section previously started───╯The main label
Section titled “The main label”The processor won’t know where to start executing the program unless we tell it.
We use a label to indicate the starting point of the program:
main:And, as it’s under the .text section:
.textmain:You might think this should work now, but it won’t quit for one reason:
If there’s no instructions after a label, it can’t actually create the
mainlabel in the output binary, because there’s nothing to attach it to!
It would give us this error:
Error: found end of input but expected \n, directive, instruction, or label ╭─[ assembly:2:6 ] │ 2 │ main: │ │ │ ╰─ Unexpected input───╯So we need at least one instruction after the label.
Technically, this could be anything and it would compile fine. But to run the program without errors, we need to tell the processor to exit.
If we don’t tell it to exit, it will just continue executing whatever random data is in memory after our program, which will likely lead to an error.
The ecall instruction
Section titled “The ecall instruction”To tell the processor to exit the program cleanly, we use the ecall
instruction:
ecallWithin the context of our program, it looks like this:
.textmain: ecallecall is an instruction that makes a system call to the operating system.
The exit system call
Section titled “The exit system call”You may thinkg we’re now done, however, we need to actually tell it which
system call we want to make. To do that, we move a value into the a7 (or
x17) register before the ecall instruction.
To move a value into a register, we use the li (load immediate) instruction.
We’ll cover how to use it in more detail later!
For exiting a program, the system call number is 10. At least, it is for the
emulator we are using. So we would do this:
.textmain: li x17, 10 ecallIn this case, it tells the operating system to terminate the program, so it stops any garbage instructions that might be after it from being executed.
And there we have it! The smallest RISC-V program that compiles and runs without errors.
Of course… the program doesn’t do anything useful. But it’s a start! All
our future RISC-V programs will build on this basic structure, changing what’s
after the main: label to do more interesting things.