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:
- 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).
- Identify what each operand-inspector pane shows for a given binary op, and reconcile against the stack-state delta (Apply; Tab 4 UI contract).
- 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).
- 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).
- 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
- Modern web browser (Chromium-family preferred)
- VM Stack Machine Simulator open at
https://virtuscyberacademy.org/workbench/static/vm-stack-machine.html - VM segment cheat sheet open in a second tab
- Ch 7 prose §§7.3-7.6 re-read
- Paper notebook for stack-state predictions (do NOT step before you predict)
- Lab 5.2.5 step-through visualizer worksheet submitted PASS (the predict-then-verify discipline is the same; this lab assumes you have done one cycle)
Step-by-Step Procedure
This lab takes ~75 minutes. Plan one sitting.
Stage 1 - Load the tool and walk a preloaded example
- Step 1. Open the tool at the URL above. Confirm you see five panes: Stack / Operand inspector / Program source / Trace log / Memory segments. The status bar should read "Ready · 0 steps executed".
- Step 2. From the dropdown, pick
ex-arithmetic-chain("(10 + 7) - (-3) = 20"). The source pane fills with 6 VM ops. The stack pane is empty (depth 0). - Step 3. Without stepping, read the source. Predict: after all 6 ops execute, what value will be on top of the stack? Write your prediction in Table A row 1.
- Step 4. Click Step once. Observe: the stack pane now shows depth 1 with value 10; the trace log has a new line; the operand inspector is idle (the first op is a unary push, not a binary op). Fill Table A row 2.
- Step 5. Click Step five more times. After each Step, fill the corresponding row of Table A with: the stack depth, the value on top, and any operand-inspector activity.
- Step 6. Confirm the final stack-top value matches your prediction in row 1. If it does not, walk backward through your row entries and find where your mental model diverged.
Stage 2 - Walk the comparison example
- Step 7. Click Reset. From the dropdown, pick
ex-comparison. The source pane fills with 9 ops (three comparisons: eq, lt, gt). - Step 8. Predict what value sits on top of the stack at the end. (Hint: each of the three comparisons pushes one value; what are they?) Fill Table B row 1.
- Step 9. Click Step nine times. After each comparison op (steps 3, 6, 9), record the value just pushed in Table B.
- Step 10. Confirm the final stack depth. Should be 3 (one value from each comparison). Why is the stack not back to depth 0 at the end? (The comparisons leave their results on the stack; there is no
popto consume them.)
Stage 3 - Walk the bitwise example
- Step 11. Click Reset. From the dropdown, pick
ex-bitwise. The source pane fills with 8 ops exercising and, not, or. - Step 12. Click Step through the program. After each binary op (and, or) and the unary
not, record the operand-inspector entries in Table C. - Step 13. Reconcile. The trace log lines for and / not / or should match your understanding of the bitwise truth tables. For
not 0, the result should be -1 (= 0xFFFFFFFF in two's complement; bitwise complement of all-zero is all-one). Confirm the tool shows this.
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]).
- Step 14. Click Reset, clear the Source pane, and paste the program above into it.
- Step 15. Predict each step's stack state in Table D BEFORE stepping. Fill the "Predicted stack (bottom -> top)" column for all 7 rows.
- Step 16. Click Step seven times. Fill the "Observed stack (bottom -> top)" column from the stack pane.
- Step 17. Mark "match" or "miss" per row. Misses surface where your model of an op disagrees with the simulator's; the simulator is the contract.
- Step 18. Variation: change v=5 to v=10 (above the range). Predict what the final stack-top should be (0, since 10 is not in [2, 8]). Run the program; confirm.
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
- Step 19. Predict the stack state at each of the 12 steps in Table E. This is the harder prediction exercise of the lab; budget ~10 minutes.
- Step 20. Click Reset, paste the program, click Step through all 12 ops. Fill the "Observed" column.
- Step 21. Mark match/miss per row.
- Step 22. Try a=3, b=7 (swap the values). The expected result is 7 again (max stays 7), but the boolean condition
a > bis now false, so the mask path that selectsbis the one that fires. Predict and verify. Note in Table E final row.
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:
- (required) Add a
## VM Stack Machine Simulatorentry to your Toolchain Diary. The entry should reference: (a) the URL where the tool lives (https://virtuscyberacademy.org/workbench/static/vm-stack-machine.html), (b) the 5-pane UI contract (Stack with top-highlighted amber / Operand inspector / Source / Trace log / Memory segments), (c) one observation that surprised you (often: how often the stack returns to depth 0 mid-program if you balanced your pushes and pops, vs how often it climbs without bound when you forget to pop). - (recommended) Append a
## Re-encountered in csa-101-ch7-lab7.5section to your existing Lab 5.2.5 (step-through visualizer) entry. Both tools show machine state directly; the step-through visualizer shows architectural registers + memory at the CPU level, while today's simulator shows the VM abstraction one level above. Note which level felt easier to predict.
Submission Checklist
- This worksheet, with Tables A, B, C, D, E filled
- All 4 Reflection Prompts answered
- Predicted-stack columns in Tables D and E filled BEFORE the Observed columns (or honest acknowledgement if not)
- Table E "Variation: a=3, b=7" entry filled with the explanation of which mask path fired
- Toolchain Diary entry for the VM Stack Machine Simulator added
Pass/Fail Self-Evidence (Tier 1 of the rubric)
Every gate must be checked.
- Gate 1. Predictions in Tables D and E filled before observations (the predict-then-verify discipline is what makes this lab worth doing).
- Gate 2. Table A row 7 (sub final) shows stack-top = 20, matching the example's comment
(10 + 7) - (-3) = 20. - Gate 3. Table D step 7 (and) shows stack-top = -1, confirming "5 is in [2, 8]".
- Gate 4. Table E step 12 (or) shows stack-top = 7, confirming max(7, 3) = 7.
- Gate 5. Reflection 4 (the brief's headline) names a specific dynamic property the simulator made visible.
If any gate is unchecked, do not submit yet.
Common Pitfalls
The five most common Lab 7.5 first-attempt failures:
- 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.
- 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
andmask pattern. - 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 isa - b, notb - a. The trace log says it explicitly:sub: 17 - 3 = 14for the arithmetic-chain example afterneg. - Forgot the Ch 7 VM has no control-flow ops. If you tried to write your max-of-two program using
if-gotoorjump, the simulator will reject the source; those land in Ch 8. The boolean-mask pattern is the Ch 7 idiom. - Seeded a segment cell expecting it to persist across Reset. Reset clears segment values too. If you set
local[0] = 42and 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.