Getting Started With RISC-V Assembly

Getting Started With RISC-V Assembly

This little article is for readers who want to learn a little bit about RISC-V assembly programming. You will learn how to compile and run programs on your x86 GNU/Linux system through the magic of cross-compiling. This exercise will set the stage for some more advanced explorations later on!

What is cross-compiling? In short, it provides a way for you to consume a program on your machine (aka, “the host”), compile it, and produce a binary that can execute on another platform (“the target.”)

If you’re an embedded developer, you’re no stranger to cross-compiling. If you don’t have a RISC-V desktop machine (some of us don’t, yet) to work on, cross-compiling will let you develop/work on your x86 machine, then build a binary that can run on your smaller, often resource-constrained, embedded device. Nobody wants to run an IDE and a compiler on a smartwatch!

Today we'll jump in by installing the toolchain you need, and the QEMU emulator (https://www.qemu.org/) with RISC-V support.

I've been using QEMU for several years as a free, easy-to-use, and highly configurable, emulator. It's been a reliable friend for installing different Operating Systems and virtualizing them. It works really well for letting us run programs compiled for a different architecture...like RISC-V

Let's jump right in!

Installing Dependencies

First, let’s install the RISC-V toolchain, like this:

sudo apt install gcc-riscv64-linux-gnu        

Then, install QEMU with RISC-V support:

sudo apt install qemu-system-misc qemu-user        

(Note: You can also build these things for yourself -- try https://github.com/riscv-collab/riscv-gnu-toolchain for starters. I'd encourage you to at least look at the source so you can explore the depth and capabilities these tools provide.)

Writing, Compiling, and Running, a Program

Finally, let’s write a little program called hello.c

Program 1. hello.c

#include <stdio.h>
int main() {
  printf("Hello, RISC-V people!\n");
  return 0;
}        

Once that's in place, you're ready to cross-compile your 'hello' program!

riscv64-linux-gnu-gcc -o hello hello.c        

Now for a digression--let's learn something about the output file ('hello'), using the 'file' command:

$ file hello

hello: ELF 64-bit LSB pie executable, UCB RISC-V, RVC, double-float ABI, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-riscv64-lp64d.so.1,BuildID[sha1]=9a610a50b3e8702b2a5a4b6ab8b15ab24bdf85d7, for GNU/Linux 4.15.0, not stripped        

There's a lot of information on that line! Depending on your particular compiler (and whether or not you added any flags to your invocation of gcc), you might see different symbols and values.

Here are some of the fields, along with their definitions:

  • ELF: Executable and Linkable Format, the standard binary format
  • 64-bit: Uses 64-bit addressing
  • LSB: Little-endian byte order
  • PIE: Position Independent Executable (can be loaded anywhere in memory because it uses relative addressing)
  • UCB: University of California, Berkeley (where RISC-V was developed)
  • RISC-V: The target instruction set architecture (of course)
  • RVC: Uses the RISC-V ‘compressed’ extension (compressed instructions take less space)

At this point, if you’re on an x86 system, you’re welcome to try executing the file from the command line (./hello) but you probably won't get too far, since the “target” of our compilation is the RISC-V platform.

This is where QEMU can help – by emulating the target, it can let us run our program! Let's see how we can execute this program using QEMU--it's pretty easy! Just try:

qemu-riscv64 -L /usr/riscv64-linux-gnu ./hello 

Hello, RISC-V people!          


(For extra credit, what does the -L flag do on that line?)

Conclusion

So, there you have it! in this little article, we setup a basic RISC-V development toolchain and the QEMU emulator.

Using cross-compilation, we were able to build a binary that's executable by a RISC-V processor, and finally, we were able to run it in an emulator.

We'll build on these tools and techniques in our next article, where we'll actually start writing some low-level code and getting to know the RISC-V a little better. Feel free to DM me with any questions, concerns, bugs (ook!), etc.


Having worked on RISC-V extensions myself, I can say beginner-friendly explanations like these are exactly what the community needs. Looking forward for further parts!

To view or add a comment, sign in

More articles by Thad Meyer

  • Advent of Code...In RISC-V?

    I don't usually spend much time with Advent of Code (https://adventofcode.com/) but I thought I'd try doing some of it…

  • Introduction to Error Detection in Digital Audio Signal Paths

    Today I'm going to give you a high-level overview of how your digital audio data signal path works, and how errors are…

    1 Comment

Others also viewed

Explore content categories