Prep: The Assembly Bridge — 20a¶
Session: Thursday Oct 1, 1h45 · Exercises: 20a_asm_bridge · Prep time: ~30 min · Lecture: Week 6 · Below Rust
QEMU deadline is today
First exercise that boots on the emulated machine; no host-side fallback.
Run oslings doctor before class. Anything red: see the
troubleshooting table
or get help in office hours now.
What you will build¶
Three short routines in RISC-V assembly, called from Rust through
global_asm! and extern "C", running bare-metal under QEMU:
a three-operand add that proves the calling convention works as you expect,
a byte-copy loop built from loads, stores, and local numeric labels,
and a baby context switch that saves four registers into one #[repr(C)]
struct, loads them from another, and returns into a different thread of
execution on a different stack. A given harness boots, calls each routine with
its edge cases (zero bytes, a context switched to itself), and the test
passes when the serial console prints OSLINGS:PASS.
Concepts you need¶
- ABI names and the register file — Week 6 · Registers have jobs · RISC-V guide: Registers
- Caller-saved vs. callee-saved — Week 6 · Caller-saved and callee-saved · RISC-V guide: caller/callee split
- The calling convention:
a0–a7,ra,sp— Week 6 · The calling convention · RISC-V guide: Calling convention - Loads, stores, and
1b/2flabels — Week 6 · Loads, stores, and local labels · RISC-V guide: Local numeric labels global_asm!,extern "C", and#[repr(C)]— Week 6 · The bridge · RISC-V guide: Assembly inside Rust- A
retthat lands somewhere else — Week 6 · Aretthat lands somewhere else - PASS,
[fail], a timeout, and getting out of QEMU — Week 6 · Running under QEMU · QEMU guide: how to get out of QEMU
Read before class¶
| What | Time |
|---|---|
Week 6 · This week, then Thursday · 20a The assembly bridge from Registers have jobs through The calling convention |
3 min |
| Week 6 · Loads, stores, and local labels and The bridge | 3 min |
Week 6 · A ret that lands somewhere else and Running under QEMU |
2 min |
Week 6 · For the exam: lb versus lbu, stack frames, register traces. Not needed today; on Midterm 1 |
2 min |
| RISC-V guide: Registers, Calling convention, Local numeric labels | 7 min |
Dev Setup: oslings doctor, and run it · QEMU guide: how to get out of QEMU |
6 min |
Mental model¶
The whole bridge fits in one leaf function that fills a two-field struct:
#[repr(C)]
pub struct Pair { pub lo: u64, pub hi: u64 } // lo at offset 0, hi at 8
core::arch::global_asm!(r#"
.globl fill_pair
fill_pair: # a0 = *mut Pair, a1 = lo, a2 = hi
sd a1, 0(a0)
sd a2, 8(a0)
ret # jalr zero, 0(ra)
"#);
extern "C" { pub fn fill_pair(p: *mut Pair, lo: u64, hi: u64); }
The arguments arrive in a0–a2 because extern "C" promised they would.
A leaf touches no callee-saved register and never overwrites ra, so nothing
is saved. The 0 and 8 are literals welded into the sd instructions; they
match the struct only because #[repr(C)] forbids reordering fields. A
kernel's context switch is this pattern scaled up: stores at hard-coded
offsets, loads from another struct, and a ret to whatever ra was just
loaded. Get one offset wrong, or load before you store, and nothing faults;
the machine runs perfectly, in the wrong place.
Check yourself¶
- A function you call uses
s3andt2as scratch. Which must it save and restore, and why?Answer
Onlys3: it is callee-saved, so the caller trusts it to survive.t2is caller-saved; the caller already assumed it was gone. retis a pseudo-instruction. What does it expand to, and what does that say about a function that overwritesrabefore returning?Answer
jalr zero, 0(ra). It jumps to whateverraholds now, so a function that loads a newrareturns somewhere else. That is the whole mechanism of a context switch.- Assembly does
sd a1, 8(a0)into a struct that is not#[repr(C)]. What can go wrong?Answer
The compiler may reorder fields, so offset 8 may be a different field. The 8 is baked into the instruction; the store silently corrupts the wrong field and no tool complains.
What "done" looks like¶
oslings run is green, then oslings submit before you leave. Not green? Submit anyway — the tests that pass earn their share — then finish it at a make-up session (office hours, on the class network) for three quarters, or anywhere else for half, and submit again.
If you finish early¶
Work Week 6 · Problem 1: Sign extension by hand, Problem 3: Offsets by hand and Problem 4: Trace a resume, then start reading Friday's prep page. Chapter 2 of the xv6 book shows where the assembly lives in a real kernel.