RISC-V · Execution

RISC-V debugger lab

From the programmer’s point of view, an RV32I processor is a state: 32 registers of 32 bits and a program counter (PC). Each instruction reads part of that state and changes another part. The debugger runs your code one instruction at a time so you see exactly what changes.

How to read the screen

  • PC is the address of the next instruction to run. The program starts at 0x00000000 and each instruction takes 4 bytes, so the line marked with ▶ sits at address PC.
  • Each register shows its value as a signed decimal and in hexadecimal. The one that changed in the last step is highlighted.
  • “Step” runs one instruction; “Run” continues to the end (or up to 10,000 instructions, to stop infinite loops). Editing the code resets the state.
  • The label table shows the address of each label: it is the target of the branches.

Debugger

PC = 0x000000000 instructions executedNext: line 2

Execution Logs

No execution logs yet.

Register Bank

x0zero00x00000000
x1ra00x00000000
x2sp00x00000000
x3gp00x00000000
x4tp00x00000000
x5t000x00000000
x6t100x00000000
x7t200x00000000
x8s000x00000000
x9s100x00000000
x10a000x00000000
x11a100x00000000
x12a200x00000000
x13a300x00000000
x14a400x00000000
x15a500x00000000
x16a600x00000000
x17a700x00000000
x18s200x00000000
x19s300x00000000
x20s400x00000000
x21s500x00000000
x22s600x00000000
x23s700x00000000
x24s800x00000000
x25s900x00000000
x26s1000x00000000
x27s1100x00000000
x28t300x00000000
x29t400x00000000
x30t500x00000000
x31t600x00000000

Labels

  • loop:0x0000000C

Supports add, sub, and, or, xor, sll, srl, sra, slt, sltu, their immediate forms, lui, auipc, conditional branches (beq, bne, blt, bge, bltu, bgeu), jal, jalr and the pseudo-instructions nop, li, mv, not, neg, j, jr, ret, beqz and bnez. There is no data memory: lw, sw and other memory accesses are not implemented. The program starts at address 0x00000000 and each instruction takes 4 bytes.

Lab exercises

Solve each one by hand before running it. “Open in the tool” loads the program into the debugger so you can check every step.

Exercise 1 · Registers and the zero register

Your first program

Two instructions load constants and the third adds them. What value ends up in a0?

addi t0, zero, 5
addi t1, zero, 7
add  a0, t0, t1
Open in the tool

Exercise 2 · The PC and unconditional jumps

An unconditional jump changes the PC

What is a0 at the end and how many instructions run?

li   a0, 1
j    skip
li   a0, 2
skip:
  addi a0, a0, 10
Open in the tool

Exercise 3 · Loops with conditional branches

Follow a loop

What is a0 when the loop exits? How many instructions run in total (counting every iteration)?

li   a0, 1
li   t0, 4
loop:
  add  a0, a0, a0
  addi t0, t0, -1
  bnez t0, loop
Open in the tool

Exercise 4 · 32-bit arithmetic

Two’s complement overflow

lui loads 0x80000 into the upper 20 bits of t0. What are t1 and t2 in decimal?

lui  t0, 0x80000
addi t1, t0, -1
slt  t2, t1, t0
Open in the tool

Exercise 5 · Function calls

Call a function with jal and return with ret

The triple routine takes a number in a0 and returns the result in a0. What are a0 and ra at the end?

li   a0, 6
jal  ra, triple
j    end
triple:
  add  a1, a0, a0
  add  a0, a1, a0
  ret
end:
  nop
Open in the tool

What the interpreter models

  • Arithmetic and logic: add, sub, and, or, xor, sll, srl, sra, slt, sltu and their immediate forms (addi, andi, ori, xori, slti, sltiu, slli, srli, srai). Results are truncated to 32-bit two’s complement, with no overflow exceptions.
  • lui and auipc, conditional branches (beq, bne, blt, bge, bltu, bgeu) to labels, jal and jalr.
  • Pseudo-instructions: nop, li (12-bit immediate), mv, not, neg, j, jr, ret, beqz and bnez, expanded to their base instruction.
  • Writing to x0 has no effect: it always reads 0.

References