Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1Learning Outcomes

We recommend pulling up the register convention section of the RISC-V Green Card. We also recommend referencing the Fundamental Steps (revisited version) of procedure calls.

2Recursive Example: factorial

Consider the below assembly implementation of factorial. We have omitted some lines for simplicity; see the full code at the end of this section.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
main:
  li a0 3
  jal ra factorial
  …
factorial:
  addi sp sp -8
  sw ra 0(sp)
  sw s0 4(sp)
  mv s0 a0
  li t0 1
  bne s0 t0 recurse
  li a0 1
  j epilogue
recurse:
  addi a0 s0 -1
  jal ra factorial
  mul a0 s0 a0
epilogue:
  lw ra 0(sp)
  lw s0 4(sp)
  addi sp sp 8
  jr ra

2.1Discussion Questions

Hover here for the RISC-V assembly.

2.2Run Demo

The below code is for reference.

3Another Recursive Example

Check it out!

1
2
3
4
5
6
7
8
int foo(int i) {
  if (i == 0) return 0;
  int a = i + foo(i-1);
  return a;
}
int j = foo(3);
int k = foo(100);
int m = j+k;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  j main
foo:          # int foo(int i)
  addi sp sp -8 # Prologue
  sw ra 0(sp)   # Prologue
  sw s0 4(sp)   # Prologue
  mv s0 a0      # Move i
  bne s0 x0 Next# if i != 0, skip this
  li a0 0       # int a = 0;
  j Epilogue    # Go to Epilogue
              # (to restore stack)
Next: 
  addi a0 s0 -1 # int j = i - 1;
  jal ra foo    # j = foo(j);
  add a0 s0 a0  # int a = i + j;
Epilogue: 
  lw ra 0(sp)   # Epilogue
  lw s0 4(sp)   # Epilogue
  addi sp sp 8  # Epilogue
  jr ra         # return a;
main:
  li a0 3       # int j = foo(3);
  jal ra foo    # call foo
  mv s0 a0      # mv rd rs1 sets rd = rs1
  li a0 100     # int k = foo(100);
  jal ra foo    # call foo
  mv s1 a0      # Saves return value in s1
  add a0 s0 s1  # int m = j+k;
Footnotes
  1. Given the mv s0 a0 instruction, we could have equivalently replaced the branch instruction bne s0 t0 recurse with bne a0 t0 recurse. The code likely uses the former to distinguish register naming conventions for register a0, which is both the first function argument and the return value. The register s0 is designated as the value of nn in factorial(n)\text{factorial}(n), and the register a0 will soon become the return value (as per line 12).

  2. Factorially is mathematically defined over all non-negative numbers, including 0!=10!= 1. The lecture code pedagogically chooses to ignore the zero case to show you bne with two non-zero register values.