This lab has been modified by your CMPT 295 instructor and creators of RISC-V ISA.
map
IF THE ANSWERS FOR EX3 and 4 are NOT COVERED DURING THE LAB, THEN THEY WILL BE DISCUSSED DURING THE CLASS
So far, we have been dealing with C program files (.c
file extension), and have been using the gcc
compiler to execute these higher-level language programs. Now, we are learning about the RISC-V assembly language, which is a lower-level language much closer to machine code. For context, gcc
takes the C code we write, first compiles this down to assembly code (e.g. x86, ARM), and then assembles this down to machine code/binary.
In this lab, we will deal with several RISC-V assembly program files, each of which have a .s
file extension. To run these, we will need to use Venus, a RISC-V simulator that you can find here. There is also a .jar
version of Venus that you can get here.
wget https://www2.cs.sfu.ca/~ashriram/Courses/CS295/assets/distrib/Venus/jvm/venus.jar
# We can also encourage you to use the online version.
# https://www2.cs.sfu.ca/~ashriram/Courses/CS295/assets/distrib/Venus/
main
function must be put first.
main
function.ecall
with argument value 10. This signals for the program to exit. The ecall
instructions are analogous to helper functions and libc/OS helpers. They allow us to do things such as print to the console or request chunks of memory from the heap.:
).#
).For the following exercises, please save your completed code in a file on your local machine. Otherwise, we will have no proof that you completed the lab exercises.
Getting started:
ex1.s
into the Venus editor.Paste the contents of ex1.s
in Venus and record your answers to the following questions. Some of the questions will require you to run the RISC-V code using Venus’ simulator tab.
.data
, .word
, .text
directives mean (i.e. what do you use them for)? Hint: think about the 4 sections of memory. If you do not know refer to RISC V assembly on tutorials pagen
stored in memory? Hint: Look at the contents of the registers.In this exercise, you will work with RISC-V assembly language to perform basic array operations and print the results to the console. You will be given two arrays, array1
and array2
, and you will write a program to add corresponding elements from these arrays and store the results in a third array, result
. Additionally, you will print the values of the arrays to the console.
la
, li
, and lw
instructions in RISC-V.ex1b.s
in the editor.Understand the Code:
la
, li
, and lw
instructions in RISC-V.Uncomment and Modify Code:
array1
to the console.array2
to the console.Understand la vs li vs lw
la
(Load Address)**la
(load address) is a pseudo-instruction that loads the address of a label (i.e., a variable in memory) into a register. reg = pointer(variable_name)
.data
var: .word 42 # Define a variable in the data section
.text
main:
la s0, var # s0 = &var
li
(Load Immediate)**li
(load immediate) is another pseudo-instruction used to directly load an immediate (constant) value into a register. reg = constantli s0, 42 # s0 = 42
lw
(Load Word)**lw
(load word) is a native MIPS instruction that reads a 32-bit (word) value from memory into a register.la
to dereference an address and retrieve the actual value stored in memory..data
var: .word 42 # Define a variable with the value 42
.text
main:
la s0, var # ptr = &var
lw s1, 0(s0) # s1 = *ptr
Open the files ex2.c
and ex2.s
. The assembly code provided (.s file) is a translation of the given C program into RISC-V.
Find/explain to yourself the following components of this assembly file.
k
.source
and dest
arrays.In this exercise, you will be implementing the factorial
function in RISC-V. This function takes in a single integer parameter n
and returns n!
. A stub of this function can be found in the file factorial.s
.
You will only need to add instructions under the factorial
label, and the argument that is passed into the function is configured to be located at the label n
. You may solve this problem using either recursion or iteration.
As a sanity check, you should make sure your function properly returns that 3! = 6
, 7! = 5040
and 8! = 40320
.
You have the option to test this using the online version of Venus, but we’ve provided a .jar
for you to test locally! We’ll be using the .jar
in the autograder so make sure to update your factorial.s
file and run the following command before you submit to verify that the output is correct. Note that you will need to have java installed to run this command.
$ wget https://www2.cs.sfu.ca/~ashriram/Courses/CS295/assets/distrib/Venus/jvm/venus.jar
$ java -jar venus.jar factorial.s
map
This exercise uses the file list_map.s
.
In this exercise, you will complete an implementation of map
on linked-lists in RISC-V. Our function will be simplified to mutate the list in-place, rather than creating and returning a new list with the modified values.
You will find it helpful to refer to the RISC-V green card to complete this exercise. If you encounter any instructions or pseudo-instructions you are unfamiliar with, use this as a resource.
Our map
procedure will take two parameters; the first parameter will be the address of the head node of a singly-linked list whose values are 32-bit integers. So, in C, the structure would be defined as:
struct node {
int value;
struct node *next;
};
Our second parameter will be the address of a function that takes one int as an argument and returns an int. We’ll use the jalr
RISC-V instruction to call this function on the list node values.
Our map
function will recursively go down the list, applying the function to each value of the list and storing the value returned in that corresponding node. In C, the function would be something like this:
void map(struct node *head, int (*f)(int))
{
if(!head) { return; }
head->value = f(head->value);
map(head->next,f);
}
If you haven’t seen the int (*f)(int)
kind of declaration before, don’t worry too much about it. Basically it means that f
is a pointer to a function, which, in C, can then be used exactly like any other function.
There are exactly nine (9) markers (8 in map
and 1 in main
) in the provided code where it says YOUR CODE HERE
.
Complete the implementation of map
by filling out each of these nine markers with the appropriate code. Furthermore, provide a sample call to map
with square
as the function argument. There are comments in the code that explain what should be accomplished at each marker. When you’ve filled in these instructions, running the code should provide you with the following output:
9 8 7 6 5 4 3 2 1 0
81 64 49 36 25 16 9 4 1 0
The first line is the original list, and the second line is the modified list after the map function (in this case square) is applied.
To test this locally, run the following command in your root lab directory (much like the one for list_map.s
):
# Make sure you have downloaded the venus.jar file
$ wget https://www2.cs.sfu.ca/~ashriram/Courses/CS295/assets/distrib/Venus/jvm/venus.jar
$ java -jar venus.jar list_map.s
Once we begin to write more complex RISC-V programs, it will become necessary to split our code into multiple files and debug/test them individually. This is impossible to do in the regular Venus web editor, but if we open the “Venus” tab, we’ll see that there is an online web terminal (with a corresponding virtual filesystem) that we can use to edit and test multiple files at once.
Note: To ensure that you don’t lose any of your work, make sure to save local copies of your files frequently.
.import
and .globl
keywords..globl
keyword can be placed in a file and defines the labels we want to expose to other files when they import this file; it’s analogous to defining a function in a header file.
factorial.s
file, you’ll notice that we export your factorial
label at the top with the .globl factorial
line at the top. This is actually how the autograder tests your function so don’t remove it!.import
line allows us to import other files into the current one. Specifically, it will import only the labels that the file specifies with the .globl
keyword. So, if we wanted to import the factorial
label in a different file, we would add the line .import factorial.s
at the top of the new file.Editor
and Simulator
tabs on Venus.Venus
tab, we’ll see a terminal-looking interface. Entering help
will show us some of the commands we can run in this terminal environment.ls
, touch
, edit
, upload
, and download
.
ls
: Lists the contents of the current directory.touch
: Creates a new empty file that we can modify later.edit
: Opens up the specified file in the “Editor” tab (Ex. edit file.s
). Note that the Cmd + S and Ctrl + S shortcuts will work to save the file in the virtual filesystem if you choose to edit a different file later. But, to ensure that your work is saved, we recommend that you periodically save local copies of every file.upload
: Opens a prompt to upload files from our local computer to the virtual filesystem. You can hold down the Ctrl or Cmd keys to select multiple files to upload. Once a file is uploaded, we can edit it in the Venus editor using the edit
command.download
: Downloads the specified files locally. You can specify multiple files to download, e.g. download file1.s file2.s
, and each one will have a corresponding prompt to ask you where to download the files.factorial.s
accepted command-line arguments, we could run the following: $ java -jar tools/venus.jar factorial.s arg1 arg2 arg3
# FYI; factorial as written does not accept command line inputs.
a0
to be the equivalent of argc
and a1
to be the equivalent of argv
.