Project 5: Vector Table Builder

Construct a correct Cortex-M vector table and reset flow.

Quick Reference

Attribute Value
Difficulty Level 3
Time Estimate 12-18 hours
Main Programming Language Assembly (Alternatives: C, Rust)
Alternative Programming Languages C, Rust
Coolness Level Level 3
Business Potential Level 1
Prerequisites Concept 5: Boot & Exceptions, Concept 6: Toolchain & ELF
Key Topics vector layout, alignment, reset flow

1. Learning Objectives

By completing this project, you will:

  1. Translate ARM concepts into observable outputs you can verify.
  2. Explain why each toolchain or hardware step is necessary.
  3. Detect and fix at least one realistic failure mode.
  4. Communicate the result clearly in a technical review or interview.

2. All Theory Needed (Per-Concept Breakdown)

Boot, Exceptions & Interrupts

Fundamentals Boot and exception handling define how control flow starts and changes when the system is interrupted. On Cortex-M, reset reads a vector table at a fixed address to obtain the initial stack pointer and reset handler. On AArch64, exception levels (EL0–EL3) define privilege and isolation across kernel, hypervisor, and secure monitor. citeturn0search6turn2search4 Interrupts are structured events with defined entry and exit behavior; when misunderstood, they cause the most common low-level failures (silent lockups, corrupted stacks, and unacknowledged interrupts).

Deep Dive Boot flow is architecture-specific, but it always starts with the hardware choosing a program counter and stack pointer. In Cortex-M, the vector table is a literal list of addresses at the start of flash (or a remapped location). The CPU loads the initial SP from offset 0 and the reset handler from offset 4; execution begins there. This is why vector tables are so critical: a single incorrect address prevents boot. In AArch64 systems, boot is more complex. Firmware (or a ROM) selects the initial exception level and execution state, then transfers control to your image. This can occur at EL2 or EL1 depending on platform; understanding the starting level is essential for setting up the MMU and interrupt controller. citeturn0search6turn2search4

Exceptions and interrupts are structured transitions. On Cortex-M, hardware automatically saves a register frame on the stack and switches to handler mode. This means your ISR is effectively running on a known stack layout; if you violate it, return from interrupt fails. AArch64 exceptions follow a different path: they trap into higher exception levels and use banked registers and exception vector tables that differ per EL. This makes exception handling on A-profile both more powerful and more complex. In practice, you must know which registers are saved by hardware and which you must save manually, and you must understand the difference between synchronous exceptions (e.g., illegal instruction) and asynchronous interrupts (e.g., timer). citeturn0search6turn2search4

Interrupt latency is also a systems-level trade-off. M-profile is designed for low-latency, deterministic responses, which is why it dominates microcontroller workloads. citeturn0search0 This is a critical difference from A-profile, where throughput and virtualization might be prioritized. When you design firmware, you need to decide which tasks are best done in an ISR versus in the main loop; an ISR that does too much can starve other interrupts and introduce jitter.

Finally, exceptions connect directly to debugging. Many “mysterious” crashes are just unhandled faults. On Cortex-M, a hard fault may indicate an invalid memory access or misaligned stack. On AArch64, synchronous exceptions reveal illegal instructions or permission violations. By understanding the exception model, you can interpret fault codes and correlate them to your assembly-level behavior, which is a core skill in systems programming and security analysis.

How this fits on projects

  • Central to P05 (Vector Table Builder), P06 (Interrupt-Driven UART), and P07 (Exception Level Lab).

Definitions & key terms

  • Vector table: Table of exception handler addresses used at reset or interrupt.
  • Exception level: Privilege tier in AArch64 (EL0–EL3). citeturn0search6turn2search4
  • ISR: Interrupt service routine.
  • HardFault: Cortex-M fault handler for severe errors.

Mental model diagram

Cortex-M Boot Sequence:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Power Applied
         │
         ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │  1. CPU comes out of reset                                      │
    │     - All registers undefined (except SP and PC)                │
    │     - Processor in Thread mode, privileged                      │
    │     - Using Main Stack Pointer (MSP)                            │
    └─────────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │  2. CPU reads address 0x00000000 (or VTOR)                      │
    │     - Loads INITIAL STACK POINTER value                         │
    │     - This value goes into SP/r13                               │
    └─────────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │  3. CPU reads address 0x00000004                                │
    │     - Loads RESET HANDLER address                               │
    │     - This value goes into PC/r15                               │
    │     - Bit 0 MUST be 1 (Thumb mode indicator)                    │
    └─────────────────────────────────────────────────────────────────┘
         │
         ▼
    ┌─────────────────────────────────────────────────────────────────┐
    │  4. Execution begins at Reset_Handler                           │
    │     - Your code starts running!                                 │
    │     - Stack is ready to use                                     │
    │     - All peripherals need initialization                       │
    └─────────────────────────────────────────────────────────────────┘


Vector Table Structure (first 16 entries are standard Cortex-M):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Offset   │  Exception #  │  Contents
    ─────────┼───────────────┼────────────────────────────────────────
    0x0000   │  -            │  Initial Stack Pointer value
    0x0004   │  1 (Reset)    │  Reset_Handler address (| 1 for Thumb)
    0x0008   │  2 (NMI)      │  NMI_Handler address
    0x000C   │  3 (HardFault)│  HardFault_Handler address
    0x0010   │  4            │  Reserved (M0+ doesn't use)
    ...      │  ...          │  ...
    0x003C   │  15 (SysTick) │  SysTick_Handler address
    0x0040   │  16 (IRQ0)    │  First peripheral interrupt
    0x0044   │  17 (IRQ1)    │  Second peripheral interrupt
    ...      │  ...          │  (RP2040 has 26 IRQs)


Example minimal vector table in assembly:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    .section .vectors, "a"
    .align 2

    .word   _stack_top          // 0x00: Initial SP
    .word   Reset_Handler + 1   // 0x04: Reset (bit 0 = Thumb)
    .word   NMI_Handler + 1     // 0x08: NMI
    .word   HardFault_Handler+1 // 0x0C: HardFault
    .word   0                   // 0x10: Reserved
    // ... more entries ...

NOTE: On RP2040, flash is at 0x10000000, so your vector table
lives there. The boot ROM copies the SP and PC from flash.

Cortex-M Boot Sequence

AArch64 Exception Levels:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    ┌─────────────────────────────────────────────────────────────────┐
    │  EL3: Secure Monitor                                            │
    │       - Highest privilege, manages secure/non-secure worlds     │
    │       - TrustZone firmware lives here                           │
    ├─────────────────────────────────────────────────────────────────┤
    │  EL2: Hypervisor                                                │
    │       - Virtualization support                                  │
    │       - Controls virtual machines                               │
    ├─────────────────────────────────────────────────────────────────┤
    │  EL1: OS Kernel                                                 │
    │       - Where Linux kernel runs                                 │
    │       - Your bare-metal code runs here!                         │
    ├─────────────────────────────────────────────────────────────────┤
    │  EL0: User Applications                                         │
    │       - Lowest privilege                                        │
    │       - Normal programs run here under Linux                    │
    └─────────────────────────────────────────────────────────────────┘

    On Raspberry Pi boot:
    ┌──────────────────────────────────────────────────────────────┐
    │ GPU firmware starts at EL3, then drops to EL2,               │
    │ loads your kernel8.img, and jumps to 0x80000 at EL2.         │
    │ Your bare-metal code typically runs at EL1 after setup.      │
    └──────────────────────────────────────────────────────────────┘

AArch64 Exception Levels

Interrupt Flow on Cortex-M:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    Main Code Running
           │
           │ ← UART receives byte
           │   Hardware sets interrupt flag
           │   NVIC sees enabled interrupt
           ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │  AUTOMATIC HARDWARE ACTIONS (you don't write code for this):    │
    │  1. Finish current instruction                                   │
    │  2. Push 8 registers to stack: r0-r3, r12, LR, PC, xPSR         │
    │  3. Load new PC from vector table (exception #)                  │
    │  4. Load 0xFFFFFFF9 into LR (EXC_RETURN)                        │
    │  5. Enter Handler mode (privileged)                              │
    └──────────────────────────────────────────────────────────────────┘
           │
           ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │  YOUR ISR EXECUTES:                                              │
    │  - Must save r4-r11 if you use them (push {r4-r7})              │
    │  - Read UART data register (clears interrupt flag)               │
    │  - Process byte (store in buffer, set flag, etc.)                │
    │  - Restore r4-r11 if saved                                       │
    │  - Return with: BX LR (the magic EXC_RETURN value)               │
    └──────────────────────────────────────────────────────────────────┘
           │
           ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │  AUTOMATIC HARDWARE ACTIONS:                                     │
    │  1. Hardware detects EXC_RETURN in LR                            │
    │  2. Pop 8 registers from stack                                   │
    │  3. Resume execution exactly where interrupted                   │
    │  4. Return to Thread mode                                        │
    └──────────────────────────────────────────────────────────────────┘
           │
           ▼
    Main Code Continues (unaware anything happened!)


Stack During Interrupt:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

    BEFORE interrupt:           AFTER entry, BEFORE ISR code:
    ┌──────────────┐           ┌──────────────┐
    │  (old data)  │           │  (old data)  │
    │              │           ├──────────────┤
    │              │           │  xPSR        │ ← +0x1C from new SP
    │              │           ├──────────────┤
    │              │           │  PC (return) │ ← +0x18
    │              │           ├──────────────┤
    │              │           │  LR          │ ← +0x14
    │              │           ├──────────────┤
    │              │           │  r12         │ ← +0x10
    │              │           ├──────────────┤
    │              │           │  r3          │ ← +0x0C
    │              │           ├──────────────┤
    │              │           │  r2          │ ← +0x08
    │              │           ├──────────────┤
    │              │           │  r1          │ ← +0x04
    │              │           ├──────────────┤
SP →│              │        SP→│  r0          │ ← +0x00 (new SP)
    └──────────────┘           └──────────────┘

    The 32 bytes (8 × 4) are pushed automatically by hardware!

Cortex-M Interrupt Flow

How it works (step-by-step, with invariants and failure modes)

  1. Boot loads initial SP and PC from the vector table (Cortex-M) or firmware-defined entry (AArch64). citeturn0search6turn2search4
  2. An interrupt triggers hardware context save and branches to the handler.
  3. Handler restores context and returns using the architecture-specific mechanism.
  4. Failure mode: wrong vector address or corrupted stack → boot hang or fault loop.

Minimal concrete example (pseudo, not runnable)

VECTOR_TABLE[Reset] -> Reset_Handler
On interrupt: push context, branch handler, restore, return

Common misconceptions

  • “Interrupt handlers are just normal functions” → They obey different entry/exit rules.
  • “Boot is just jump to main” → Boot is a structured sequence with strict alignment rules.

Check-your-understanding questions

  1. Why must the reset handler address be Thumb-aligned on Cortex-M?
  2. What does EL1 represent in AArch64?
  3. Why must ISRs be short?

Check-your-understanding answers

  1. Bit 0 of the address indicates Thumb state; if it’s wrong, the CPU faults.
  2. EL1 is the kernel-level privilege where OS code typically runs. citeturn0search6turn2search4
  3. Long ISRs increase latency and can block higher-priority interrupts.

Real-world applications

  • Firmware bootloaders, interrupt-driven I/O, and OS exception handling. citeturn0search0turn0search6

Where you’ll apply it

  • This project: see §3.1 and §5.4 in P05-vector-table-builder.md
  • P05 Vector Table Builder
  • P06 Interrupt-Driven UART
  • P07 AArch64 Exception Level Lab

References

  • AArch64 exception model and privilege levels. citeturn0search6turn2search4
  • Cortex-M profile emphasis on low-latency interrupt response. citeturn0search0

Key insights Boot and exceptions are not features you add later; they are the foundation of control flow.

Summary Once you understand boot and exceptions, most “mysterious” bare-metal failures become obvious.

Homework/Exercises to practice the concept

  1. Draw the Cortex-M vector table layout and label the first 8 entries.
  2. Explain how an interrupt differs from a synchronous exception.

Solutions to the homework/exercises

  1. The first entry is the initial SP, followed by reset, NMI, HardFault, and system handlers.
  2. Interrupts are asynchronous hardware events; synchronous exceptions are triggered by the current instruction.

Toolchain & ELF

Fundamentals Assembly alone is not executable; you need a toolchain to assemble, link, and package code into a binary format. GNU as (the GNU assembler) accepts assembly source and emits object files; the linker combines objects into an executable with sections and symbols. citeturn1search1 On most ARM systems, the object format is ELF, defined by the System V ABI family. citeturn1search4 Understanding sections, symbols, and relocations is essential for boot images, firmware layout, and disassembly.

Deep Dive The toolchain is a pipeline: source → object → linked image. The assembler parses directives, encodes instructions for the target ISA, and emits relocatable objects. The linker then resolves symbols, assigns addresses, applies relocations, and produces a final ELF file or a raw binary. This is not a black box: if your startup code lands at the wrong address or your vector table is misaligned, the linker script is responsible. The GNU assembler manual documents directive syntax and how the assembler handles sections, alignment, and symbols. citeturn1search1

ELF (Executable and Linkable Format) is the standard container for compiled objects. It defines headers, sections, and symbol tables so tools can reason about what is in a binary. citeturn1search4 ELF’s strength is transparency: you can inspect sections such as .text (code), .data (initialized data), .bss (zero-initialized data), and custom sections for vector tables or boot metadata. In embedded contexts, you often convert ELF into a raw binary that can be flashed, but the ELF remains the authoritative artifact for debugging because it contains symbols and relocation information.

Relocations are where everything connects. When the assembler emits an instruction that references a symbol whose address is not yet known, it emits a relocation entry. The linker later resolves it. This is how references to labels, functions, and global variables are patched. If you understand relocations, you can interpret why certain instructions appear in disassembly, and you can identify errors like “relocation overflow” or “undefined reference.” The same reasoning applies to position-independent code or shared libraries on A-profile systems.

In practical terms, mastering the toolchain lets you answer questions like: Why is my vector table not at the start of flash? Why does the linker place my .data in RAM but my .text in flash? Why does a symbol show up as undefined? These are the exact questions you will encounter in bare-metal ARM development, and they can only be solved by understanding ELF and the linker. The toolchain also connects to diagnostics: objdump and readelf are not just utilities; they are the microscope that lets you see what the assembler and linker actually produced.

How this fits on projects

  • Core to P01 (Toolchain Pipeline Explorer) and P10 (Capstone Monitor).

Definitions & key terms

  • Assembler: Translates assembly source into object files. citeturn1search1
  • Linker: Resolves symbols and produces an executable or binary.
  • ELF: Executable and Linkable Format for binaries. citeturn1search4
  • Relocation: A placeholder that the linker resolves to a final address.

Mental model diagram

Toolchain Flow
──────────────
Source (.s) → Assembler → Object (.o) → Linker → ELF (.elf) → Binary (.bin)
                    │                 │
               Symbols/Relocs    Sections/Addresses

How it works (step-by-step, with invariants and failure modes)

  1. Assemble source into relocatable objects.
  2. Link with a linker script or default layout.
  3. Verify ELF sections and symbols.
  4. Failure mode: wrong section placement → boot hangs or interrupts jump to wrong address.

Minimal concrete example (pseudo, not runnable)

.section .vectors
.word reset_handler
.linker: place .vectors at flash start

Common misconceptions

  • “ELF is only for OS programs” → It is central in embedded, too. citeturn1search4
  • “Linker script is optional” → Not when you need precise memory layout.

Check-your-understanding questions

  1. What is the role of a relocation entry?
  2. Why do embedded projects often convert ELF to raw binary?
  3. What is the difference between .text and .bss?

Check-your-understanding answers

  1. It records a reference the linker must patch with a final address.
  2. Flashing tools often want raw bytes, but ELF holds symbols for debugging.
  3. .text holds code; .bss holds zero-initialized data.

Real-world applications

  • Firmware image layout, boot loaders, and disassembly tooling.

Where you’ll apply it

  • This project: see §3.1 and §5.4 in P05-vector-table-builder.md
  • P01 Toolchain Pipeline Explorer
  • P10 Capstone Monitor

References

  • GNU assembler manual. citeturn1search1
  • ELF format and ABI overview. citeturn1search4

Key insights The toolchain is the bridge between assembly and hardware; without it, nothing runs.

Summary Understanding ELF and linking turns build failures into solvable layout problems.

Homework/Exercises to practice the concept

  1. Identify three sections you expect in a bare-metal ELF and explain why.
  2. Explain how a symbol reference becomes a concrete address.

Solutions to the homework/exercises

  1. .text for code, .data for initialized globals, .bss for zeroed globals.
  2. The assembler emits a relocation that the linker resolves to the final address.

3. Project Specification

3.1 What You Will Build

A bootable image with a validated vector table and reset handler.

3.2 Functional Requirements

  1. Requirement 1: Place vector table at required address
  2. Requirement 2: Initialize stack pointer and jump to reset handler
  3. Requirement 3: Emit a boot banner for verification

3.3 Non-Functional Requirements

  • Boot must be deterministic across runs

3.4 Example Usage / Output

$ bootlab-run
[BOOT] Vector table OK
[BOOT] Reset handler entered

$ bootlab-run --corrupt-table
error: invalid vector table checksum
exit code: 1

3.5 Data Formats / Schemas / Protocols

  • Vector table entries: address list

3.6 Edge Cases

  • Misaligned table
  • Invalid reset handler address

3.7 Real World Outcome

This is the golden reference for success:

  • A board or emulator consistently boots into your reset handler.

3.7.1 How to Run (Copy/Paste)

  • Build: follow the toolchain steps defined in this guide
  • Run: use the CLI examples in §3.4 with fixed inputs
  • Expected directory: project root

3.7.2 Golden Path Demo (Deterministic)

Run with a fixed input set and confirm output matches §3.4 exactly.

3.7.3 If CLI: Exact Terminal Transcript

$ bootlab-run
[BOOT] Vector table OK
[BOOT] Reset handler entered

$ bootlab-run --corrupt-table
error: invalid vector table checksum
exit code: 1

4. Solution Architecture

4.1 High-Level Design

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│ Input Layer  │───▶│ Core Logic   │───▶│ Output Layer │
└──────────────┘     └──────────────┘     └──────────────┘

4.2 Key Components

Component Responsibility Key Decisions
Input Parser Validate and normalize input Strict error handling
Core Engine Perform the main computation Deterministic paths
Reporter Produce user-facing output Stable formatting

4.3 Data Structures (No Full Code)

Record Entry {
  name: string
  fields: list
  notes: text
}

4.4 Algorithm Overview

Key Algorithm: Core Flow

  1. Parse input and validate parameters.
  2. Execute the core transformation or analysis.
  3. Emit deterministic output or error summary.

Complexity Analysis:

  • Time: O(n) in the size of input records
  • Space: O(n) for stored mappings and logs

5. Implementation Guide

5.1 Development Environment Setup

# Install toolchain and verify versions
toolchain --version

5.2 Project Structure

project-root/
├── src/
│   ├── core
│   └── io
├── tests/
│   └── fixtures
├── docs/
└── README.md

5.3 The Core Question You’re Answering

“Construct a correct Cortex-M vector table and reset flow.”

5.4 Concepts You Must Understand First

Stop and research these before coding:

  1. Boot, Exceptions & Interrupts
    • What is the key invariant you must preserve?
  2. Toolchain & ELF
    • What is the key invariant you must preserve?

5.5 Questions to Guide Your Design

  1. Data Flow
    • How does input become output?
    • Which steps must be deterministic?
  2. Validation
    • What is the simplest test that proves correctness?
    • How will you detect regressions?

5.6 Thinking Exercise

Trace the Critical Path

Write a step-by-step trace of the most important workflow in this project.

Questions to answer:

  • Where could a subtle bug hide?
  • What would you log to prove correctness?

5.7 The Interview Questions They’ll Ask

  1. “What is the core invariant this project relies on?”
  2. “How would you debug a failure in this workflow?”
  3. “What trade-offs did you make in design?”
  4. “How does this map to real hardware or toolchains?”
  5. “How do you prove your output is correct?”

5.8 Hints in Layers

Hint 1: Start small Focus on the smallest input that still demonstrates the concept.

Hint 2: Make output deterministic Fix inputs and produce stable logs before expanding functionality.

Hint 3: Validate against a known reference Compare with a known-good output or specification.

Hint 4: Add instrumentation Log internal steps so you can verify each phase explicitly.

5.9 Books That Will Help

Topic Book Chapter
Core concept “ARM Assembly Language” by William Hohl Ch. 3-5
Binary formats “Linkers and Loaders” by John R. Levine Ch. 1-3

5.10 Implementation Phases

Phase 1: Foundation (2-4 hours)

Goals:

  • Establish a minimal working pipeline
  • Validate one end-to-end path Tasks:
    1. Build the smallest viable input and output
    2. Verify outputs against a reference Checkpoint: Output matches expected golden path

Phase 2: Core Functionality (4-8 hours)

Goals:

  • Implement main logic and validation
  • Add structured error handling Tasks:
    1. Implement the core transformation
    2. Add deterministic reporting Checkpoint: Core tests pass reliably

Phase 3: Polish & Edge Cases (2-4 hours)

Goals:

  • Cover edge cases
  • Improve output clarity Tasks:
    1. Add negative tests
    2. Document limitations Checkpoint: All edge cases handled gracefully

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Input format Free-form vs structured Structured Easier validation
Output format Human vs machine Both Supports verification and tooling

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Validate core logic Field parsing, bounds checks
Integration Tests Validate full flow End-to-end CLI runs
Edge Case Tests Validate boundaries Empty input, invalid flags

6.2 Critical Test Cases

  1. Golden path: Fixed input produces known output.
  2. Invalid input: Error path triggers correct exit code.
  3. Boundary case: Maximum supported value handled correctly.

6.3 Test Data

Input: fixed seed or fixed fixture
Expected: exact output text from §3.4

7. Common Pitfalls & Debugging

Pitfall Symptom Solution
Misaligned assumptions Unexpected output Re-check invariants
Missing validation Silent failures Add explicit checks
Non-determinism Flaky output Fix inputs and seeds

7.2 Debugging Strategies

  • Trace everything: Log each step with stable ordering
  • Compare against reference: Use known-good outputs

7.3 Performance Traps

  • Avoid repeated parsing of the same input; cache results when possible

8. Extensions & Challenges

8.1 Beginner Extensions

  • Add one extra output format
  • Add a help screen with examples

8.2 Intermediate Extensions

  • Add a verification mode that compares two outputs
  • Add structured JSON output

8.3 Advanced Extensions

  • Add a batch mode for large inputs
  • Add cross-target comparisons (M vs A profile)

9. Real-World Connections

9.1 Industry Applications

  • Firmware bring-up: use the same checks to validate early boot images
  • Security audits: analyze binaries for ABI or control-flow correctness
  • binutils: source of many ARM tooling workflows
  • QEMU: emulator used for ARM testing

9.3 Interview Relevance

  • Explains why ARM behavior differs across profiles
  • Demonstrates toolchain literacy and debugging rigor

10. Resources

10.1 Essential Reading

  • “ARM Assembly Language” by William Hohl - practical instruction usage
  • “Linkers and Loaders” by John R. Levine - binary layout

10.2 Video Resources

  • ARM architecture overview talks and lectures

10.3 Tools & Documentation

  • GNU binutils documentation
  • Arm developer documentation
  • This project connects with: P01-toolchain-pipeline-explorer.md, P02-register-stack-visualizer.md, P03-thumb-encoder-decoder.md

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain the core concept without notes
  • I can explain why my design choices were necessary
  • I can describe one realistic failure mode

11.2 Implementation

  • All functional requirements are met
  • Tests pass deterministically
  • Edge cases are documented

11.3 Growth

  • I can describe what I would improve next time
  • I can explain this project in an interview

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Core functionality works on reference inputs
  • Deterministic golden path is documented
  • At least one failure path is demonstrated

Full Completion:

  • All minimum criteria plus:
  • Edge cases are covered with tests
  • Output format is stable and documented

Excellence (Going Above & Beyond):

  • Add a comparison against a second target
  • Provide a short write-up of lessons learned