Classroom Glossary Public site

VM Stack Machine Workout (Lab 7.1-7.2 Tier-1 Companion)

3,145 words · worksheet

This is a Tier-1-graded worksheet. Submit only this filled worksheet. The Tier-2 translator artifacts live on Lab 7.1 (stack-arithmetic translator) and Lab 7.2 (segment translator); today's lab is the interactive-driven companion that exposes the per-op stack state your translator's emitted code is supposed to produce.

Purpose

Lab 7.1 had you write a translator that consumes VM bytecode and emits RV32I-Lite assembly. That work happens in code. Today's worksheet drives the VM Stack Machine Simulator (/workbench/static/vm-stack-machine.html) to show, op by op, exactly what each line of VM bytecode is supposed to do to the stack. Where your translator's emitted RV32I-Lite differs from what this tool says, the tool is the contract (it is the abstract machine your assembly is supposed to faithfully simulate; if it disagrees with your translator, the translator is wrong).

The tool's five panes (Stack with top highlighted amber / Operand inspector / Program source / Trace log / Memory segments) update every Step click. The stack pane shows the depth and the topmost-occupied value; the operand inspector shows the two values a binary op pops plus the result it pushes; the eight segment cards along the bottom show the segment base values you can seed (click any cell to set it). You use those affordances to answer the worksheet's two kinds of question: predictive (what is on top of the stack after the next op?) and observational (the stack pane shows depth 3 with -1 on top; which op put that -1 there, and what does -1 mean in this VM?).

The pedagogical claim of Ch 7 §7.3 is that the VM is defined by what each op does to the stack. The tool makes that claim visual: every op has exactly one stack-state delta, and the trace log captures it as a human-readable line. The pedagogical claim of §7.6 is that the eight segments are named windows into the host RAM. The segment-cards pane makes that visual too: the segments are visibly separate; push and pop into them have visibly different effects from push/pop on constant.

The deeper purpose: this lab calibrates your understanding of the VM-as-abstract-machine against the canonical model. Lab 7.1's translator emits assembly that has to faithfully realize the model; if you cannot predict what a VM op does to the stack, your translator's emitted assembly is guessed, not derived.

Learning Objectives

By the end of this worksheet, you will be able to:

  1. Predict the stack-state delta for every one of the 11 VM ops (push, pop, add, sub, neg, eq, lt, gt, and, or, not), reading the §7.3 prose into a one-line "before -> after" sketch (Apply; Ch 7 §7.3).
  2. Identify what each operand-inspector pane shows for a given binary op, and reconcile against the stack-state delta (Apply; Tab 4 UI contract).
  3. Explain the Virtus VM comparison convention (eq, lt, gt push -1 for true and 0 for false) in the context of why the bitwise ops then compose with the comparison results (Analyze; §7.3.4 + §7.3.5).
  4. Implement a small VM program (~7-12 ops) that exercises every op category, by predicting each step's stack state before running and explaining any mismatch (Apply + Evaluate; §7.3 + §7.6).
  5. Articulate one observation about the stack machine that the §7.3 prose alone could not make visible, in 3-5 sentences (Evaluate; §7.3 vs hands-on stepping).

Equipment Checklist

Step-by-Step Procedure

This lab takes ~75 minutes. Plan one sitting.

Stage 1 - Load the tool and walk a preloaded example

Stage 2 - Walk the comparison example

Stage 3 - Walk the bitwise example

Stage 4 - Implement a student program: range-check

This program tests whether a value is in a range [a, b]. The expected output is one value on the stack: -1 if in range, 0 if not. Algorithm: push (v > a) AND (v < b); both inequalities push -1 for true and 0 for false; the AND combines them.

The program for v=5, a=2, b=8 is:

push constant 5
push constant 2
gt
push constant 5
push constant 8
lt
and

7 ops; the expected stack top at the end is -1 (since 5 is in [2, 8]).

Stage 5 - Implement a more ambitious program: max-of-two-without-branching

The Ch 7 VM has no control-flow ops (no if-goto or goto; those land in Ch 8). So conditional logic has to be expressed with boolean masks: compute the boolean condition as -1 or 0, AND it with the desired value, OR with the alternate. The pattern that comes out is:

max(a, b) = ((a > b) AND a) OR ((NOT (a > b)) AND b)

For a=7, b=3, max(a, b) = 7. The program is 12 ops:

push constant 7
push constant 3
gt
push constant 7
and
push constant 7
push constant 3
gt
not
push constant 3
and
or

Stage 6 - Reflection

Answer the 4 reflection prompts below in 2-4 sentences each.

Data Entry Tables

Table A - Canonical Arithmetic-Chain Walk (Steps 3-6)

# What Predicted / Observed
1 Final stack-top value after all 6 ops (predict before stepping) _____
2 Step 1 (push constant 10): stack-top = ___; depth = ___ _____
3 Step 2 (push constant 7): stack-top = ___; depth = ___ _____
4 Step 3 (add): stack-top = ___; operand inspector shows a = ___, b = ___, result = ___ _____
5 Step 4 (push constant 3): stack-top = ___; depth = ___ _____
6 Step 5 (neg): stack-top = ___; operand inspector shows operand = ___, result = ___ _____
7 Step 6 (sub): stack-top = ___; operand inspector shows a = ___, b = ___, result = ___ _____
Final prediction matched final observation? [ ] Yes [ ] No (explain in Reflection 3)

Table B - Comparison Example Walk (Steps 8-9)

# After step Value just pushed What it means (-1 = true; 0 = false)
0 (predicted final state; bottom -> top): ___, ___, ___ _________________________
1 Step 3 (eq on 5 and 5) _____ 5 == 5 is _____
2 Step 6 (lt on 5 and 3) _____ 5 < 3 is _____
3 Step 9 (gt on 5 and 3) _____ 5 > 3 is _____

Why is the stack still depth 3 at the end, not depth 0? _____________________________________________

Table C - Bitwise Example Operand-Inspector Observations (Steps 12-13)

# Op a (under top) b (top) result Note
1 and (after push 255 + push 15) _____ _____ _____ 0xFF & 0x0F = ?
2 not (after push 0) (unary) _____ _____ NOT 0 = ? (bitwise complement of 0)
3 or (after push 15 + push 240) _____ _____ _____ 0x0F

Table D - Student Program: Range-Check, v=5, a=2, b=8 (Steps 14-18)

Step Op Predicted stack (bottom -> top) Observed stack Match
1 push constant 5 [5] _____ [ ]
2 push constant 2 [5, 2] _____ [ ]
3 gt [____] _____ [ ]
4 push constant 5 [____, 5] _____ [ ]
5 push constant 8 [____, 5, 8] _____ [ ]
6 lt [____, ____] _____ [ ]
7 and [____] _____ [ ]
Variation: v=10, a=2, b=8 (re-run; final stack-top = ___) [ ]

Table E - Student Program: max(7, 3) Without Branching (Steps 19-22)

Step Op Predicted stack (bottom -> top) Observed stack Match
1 push constant 7 [7] _____ [ ]
2 push constant 3 [7, 3] _____ [ ]
3 gt [____] _____ [ ]
4 push constant 7 [____, 7] _____ [ ]
5 and [____] _____ [ ]
6 push constant 7 [____, 7] _____ [ ]
7 push constant 3 [____, 7, 3] _____ [ ]
8 gt [____, ____] _____ [ ]
9 not [____, ____] _____ [ ]
10 push constant 3 [____, ____, 3] _____ [ ]
11 and [____, ____] _____ [ ]
12 or [____] _____ [ ]
Variation: a=3, b=7 (swap) (re-run; final stack-top = ___; explain which mask path fired) _____________________________________________

Reflection Prompts

Answer in 2-4 sentences each.

1. The Virtus VM has no control-flow ops at this layer (if-goto and goto arrive in Ch 8). The Stage 5 max-of-two program had to express a conditional as boolean masks ((cond AND a) OR (NOT cond AND b)). What was uncomfortable about that pattern? (The honest answer is fine; the pattern feels like a workaround the first time you see it, and it is. The point of Ch 8 is to give you if-goto so you do not have to use the mask pattern in real code.)



2. The comparison ops push -1 for true and 0 for false. Why -1 and not +1? (Hint: the and op in Stage 5 works only because -1 has every bit set; -1 AND x = x for any x. If true were represented as +1, the mask pattern would not compose with and the same way.)



3. The tool's segment cards along the bottom let you click any cell to seed a value. Pick the ex-segments preloaded example, seed local[0] = 42 by clicking the cell, and run the program. How does pushing from a segment differ from pushing a constant, in terms of what the simulator shows? (Hint: the stack pane shows the same kind of cell, but the segment pane shows the source location; together they tell you not just "what is on the stack" but "where did it come from".)



4. The brief's headline question. What did you see using the stack-machine simulator that the Ch 7 prose alone could not show you? (Hint: prose can tell you "add pops two and pushes one"; the simulator shows you the depth-2 stack become depth-1 in real time and the operand inspector display the exact values that participated. A good answer names a specific dynamic property of the machine - the size of the stack between two ops, the timing of when an operand inspector lights up, the visible bridge between a segment cell and a stack cell - that the prose could only describe in static terms.)




Toolchain Diary Trigger

This worksheet introduces one new tool:

Submission Checklist

Pass/Fail Self-Evidence (Tier 1 of the rubric)

Every gate must be checked.

If any gate is unchecked, do not submit yet.

Common Pitfalls

The five most common Lab 7.5 first-attempt failures:

  1. Stepped before predicting. Tables D and E lose calibration value once the predictions are back-filled. If you stepped first, re-do with the variation values (v=10 for D; a=3,b=7 for E) so the predict-then-verify discipline still applies.
  2. Confused -1 with 1 for "true". The Virtus VM convention is -1 for true (all bits set) and 0 for false (all bits clear). +1 is not "true" here; it is the integer 1. This matters for the and mask pattern.
  3. Misread the operand inspector's a/b labels. "a" is the operand under the top (deeper in the stack); "b" is the top. For sub, the operation is a - b, not b - a. The trace log says it explicitly: sub: 17 - 3 = 14 for the arithmetic-chain example after neg.
  4. Forgot the Ch 7 VM has no control-flow ops. If you tried to write your max-of-two program using if-goto or jump, the simulator will reject the source; those land in Ch 8. The boolean-mask pattern is the Ch 7 idiom.
  5. Seeded a segment cell expecting it to persist across Reset. Reset clears segment values too. If you set local[0] = 42 and then Reset, re-seed the cell before running the segment-using program.

Forward Pointer

Lab 7.1 (Tier-2 Stack Arithmetic Translator) is where you write the Python that converts the same VM bytecode you stepped here today into RV32I-Lite assembly. Every Step click on today's simulator corresponds to a fixed RV32I-Lite emission pattern in your translator; the simulator is the contract your translator must faithfully realize. Lab 7.1's grading checks bit-equivalence between your translator's emitted hex and the academy reference.

Lab 7.2 (Tier-2 Memory Segment Translator) extends Lab 7.1's stack-arithmetic translator with the eight memory segments. The segment cards you clicked today (constant, argument, local, static, this, that, pointer, temp) are exactly the cards your translator's emission patterns must address. Click-to-seed in today's simulator is the runtime analog of your translator's compile-time segment-base resolution.

Lab 7.3 (Tier-2 End-to-End on Student Silicon) runs your translator's output on the real CPU you built in Ch 5. The simulator's stack pane shows the same logical stack state that, on real silicon, lives at addresses 0x00010840 and up per the vm-segment-cheat-sheet handout. Today's tool abstracts the address; Lab 7.3 makes it concrete.

Lab 8.x (Ch 8 VM II) adds the control-flow ops (label, goto, if-goto) and the function-call protocol (call, function, return). The boolean-mask pattern you used in today's Stage 5 is what you no longer need once if-goto arrives in Ch 8; your max-of-two program becomes a branch-and-fall-through pattern that is faster, smaller, and reads more naturally.

Beyond Ch 7: every later chapter that interprets VM bytecode leans on today's calibration. Ch 9-11 (compiler frontend + codegen) emits VM bytecode that, run on today's simulator, produces the stack state Ch 12 (Virtus OS) services then read. The simulator is the calibration; every later layer inherits it.


LAB WORKSHEET COMPLETE - Lab 7.5 v1.0; Tier-1-graded worksheet-completion; YAML frontmatter (12 fields incl grading_disposition: Tier-1 worksheet-completion. stack-state predictions in Tables B and D filled BEFORE observations; reflection prompts answered; no REPORT.md or RUBRIC-SELF.md (those land on Tier-2 translator labs 7.1 and 7.2)) + 5 Bloom-ordered LOs tied to Ch 7 §7.3 (11 ops) + §7.6 (8 segments) + tool UI contract + §7.3.4 + 7.3.5 comparison convention + §7.3 vs hands-on-stepping integration + 6-item Equipment Checklist (incl tool URL + segment cheat-sheet open + Ch 7 prose re-read + paper-notebook-for-prediction discipline + Lab 5.2.5 PASS gate) + 6-stage / 22-step Procedure (load tool + walk arithmetic-chain example -> walk comparison example -> walk bitwise example -> implement range-check student program with predict-then-verify -> implement max-of-two-without-branching student program with predict-then-verify -> reflect) + 5 Data Tables (A: 7-row arithmetic-chain step walk / B: 4-row comparison walk with -1-vs-0 convention / C: 3-row bitwise operand-inspector observations / D: 7-row range-check student program predict-then-verify / E: 12-row max-of-two student program predict-then-verify with a-b-swap variation) + 4 Reflection Prompts (boolean-mask-feels-like-workaround acknowledgement + why-minus-one-not-plus-one for "true" + segment-pane-shows-where-value-came-from + the-brief's-headline what-did-you-see-with-simulator-not-with-prose) + Toolchain Diary Trigger (one new tool: VM Stack Machine Simulator with URL + 5-pane UI contract + observational surprise; recommended re-encounter section on Lab 5.2.5 step-through visualizer comparing the two abstraction levels) + Submission Checklist (5 items) + Pass/Fail Self-Evidence (5 Tier-1 gates) + Common Pitfalls (5 numbered) + Forward Pointer to Lab 7.1 (Tier-2 translator contract; today's simulator is what your translator must realize) + Lab 7.2 (segment translator; the segment cards click-to-seed is the runtime analog) + Lab 7.3 (end-to-end on silicon; addresses become concrete) + Lab 8.x (Ch 8 control-flow ops retire the boolean-mask pattern) + closing thesis on simulator-as-calibration-for-every-later-layer; references VM Stack Machine spec from R-INTERACTIVE-CSA-101-CH7-VM-STACK-MACHINE-2026-05-13 (commit b0637ed) + the cross-chapter-vm-segment-cheat-sheet.md handout via Reflection 3 + the §7.3.4 minus-one-true convention via Reflection 2; no new Petzold weaves added per voice-contract.