diff --git a/README.md b/README.md
index 5aa6b8c..d975fa0 100644
--- a/README.md
+++ b/README.md
@@ -22,9 +22,9 @@ By using this repository and course, you acknowledge and agree that:
-# Today's Tutorial [September 5, 2026]
-## Lesson 287: Embedded Hacking Course (Chapter 5: Intro To Variables)
-This chapter covers an introduction to variables as it relates to embedded development on the Pico 2.
+# Today's Tutorial [September 6, 2026]
+## Lesson 288: Embedded Hacking Course (Chapter 6: Debugging Intro To Variables)
+This chapter covers debugging an introduction to variables as it relates to embedded development on the Pico 2.
-> Click [HERE](https://github.com/mytechnotalent/Embedded-Hacking/blob/main/Embedded-Hacking.pdf) to read the FREE pdf book.
diff --git a/WEEK01/WEEK01a.md b/WEEK01/WEEK01a.md
index 4d0b587..7a2bae8 100644
--- a/WEEK01/WEEK01a.md
+++ b/WEEK01/WEEK01a.md
@@ -148,8 +148,8 @@ __asm volatile(
This lowers `sp` by 8 bytes. At the new stack pointer, the saved values are:
```text
-[sp] = r4
-[sp + 4] = lr
+[sp + 4] = lr (higher address, visual top)
+[sp] = r4 (lower address) <- SP <- TOP OF STACK
```
##### Second Push: `push {r3, r2, r6}`
@@ -159,17 +159,17 @@ This is deliberately written in a confusing order. The source says `r3` first, b
After one `si`, the stack layout proves the actual rule:
```text
-[sp] = r2
-[sp + 4] = r3
-[sp + 8] = r6
-[sp + 12] = r4
-[sp + 16] = lr
+[sp + 16] = lr (highest address, visual top)
+[sp + 12] = r4
+[sp + 8] = r6
+[sp + 4] = r3
+[sp] = r2 (lowest address) <- SP <- TOP OF STACK
```
The first three words were written by this instruction; `r4` and `lr` remain from
the preceding `push {r4, lr}`. The lowest register number in this push is stored
-at the lowest address. Because the stack grows down, `r6` is closest to the stack
-pointer value from before this instruction.
+at the lowest address. Because the stack grows down, `[sp]` is the lower address
+and the older `lr` at `[sp + 16]` is the higher address at the visual top.
##### High Registers: `stmdb sp!, {r9, r10}`
@@ -178,8 +178,8 @@ The 16-bit Thumb `push` encoding cannot encode high registers `r8` through `r12`
`r10`.
```text
-[sp] = r9
-[sp + 4] = r10
+[sp + 4] = r10 (higher address, visual top)
+[sp] = r9 (lower address) <- SP <- TOP OF STACK
```
##### The Restore Instructions
@@ -277,7 +277,9 @@ c
disas main
```
-You should see this instruction pattern. Your addresses can differ after a rebuild.
+You should see this instruction pattern from the current `build\0x0001a_stack.elf`.
+The instruction addresses are determined by the ELF. The register contents shown
+later are live target state and are not determined by the ELF.
```text
=> main: push {r3, lr}
@@ -291,7 +293,7 @@ You should see this instruction pattern. Your addresses can differ after a rebui
main+24: b.n main+6
```
-Notice that GDB displays `{r2, r3, r6}`, not the source spelling `{r3, r2, r6}`. That is the encoded register set in canonical order. Depending on the disassembler, register `r10` may be displayed as its conventional alias, `sl`.
+Notice that GDB displays `{r2, r3, r6}`, not the source spelling `{r3, r2, r6}`. That is the encoded register set in canonical order. Some disassemblers display `r10` as its conventional alias, `sl`; `{r9, sl}` and `{r9, r10}` name the same register set.
### Basic GDB Commands: Your First Steps
@@ -308,125 +310,330 @@ Notice that GDB displays `{r2, r3, r6}`, not the source spelling `{r3, r2, r6}`.
### Watching the Stack Change
+> **Important: the instruction addresses and stack offsets below come from the
+> current ELF. The Step 4 register capture is from the live GDB session shown
+> here. Register contents and old SRAM words are target state, not constants
+> that can be recovered from the ELF. The deterministic rule is that `push
+> {r4, lr}` decreases `sp` by 8 bytes, stores `r4` at the new `[sp]`, and
+> stores `lr` at `[sp + 4]`.
+
##### Step 1: Inspect the Stack Before the Compiler Prologue
At the breakpoint, GDB is paused before `push {r3, lr}`. Inspect the current stack pointer and the two words below it:
```gdb
-p/x $sp
-x/2wx $sp-8
+(gdb) p/x $sp
+$1 = 0x20082000
+(gdb) x/2wx $sp-8
+0x20081ff8: 0x88526891 0x10000187
```
+The stack pointer is at `0x20082000`. The two words below it contain previous values (before the prologue).
+
##### Step 2: Execute One Instruction
-```gdb
-si
-```
-
-The arrow moves to `bl stdio_init_all`. Inspect what the compiler prologue placed on the stack:
+Execute the compiler prologue `push {r3, lr}`:
```gdb
-p/x $sp
-x/wx $sp
-x/wx $sp+4
+(gdb) si
+0x100001e2 7 stdio_init_all();
+(gdb) p/x $sp
+$2 = 0x20081ff8
+(gdb) p/x $r3
+$3 = 0xe000ed08
+(gdb) x/wx $sp
+0x20081ff8: 0xe000ed08
+(gdb) p/x $lr
+$4 = 0x1000018b
+(gdb) x/wx $sp+4
+0x20081ffc: 0x1000018b
```
-The stack pointer moved down 8 bytes. `[sp]` is the saved `r3`; `[sp+4]` is the saved `lr`.
+The prologue saved two values to the stack:
+```text
+[sp + 4] = 0x1000018b (lr, higher address, visual top)
+[sp] = 0xe000ed08 (r3, lower address) <- SP <- TOP OF STACK
+```
+
+**Stack layout after prologue** (memory grows downward; **higher hex addresses = deeper in stack = older data**):
+
+```text
+Address Pointer Value Label
+0x20082000 ---------- ---------- (previous data — HIGHEST address, visual top)
+0x20081ffc ---------- 0x1000018b (lr, higher address)
+0x20081ff8 <- [sp] 0xe000ed08 (r3, lowest address) <- SP <- TOP OF STACK
+
+MEMORY ORDER: 0x20081ff8 < 0x20081ffc < 0x20082000
+ (visual bottom) (visual top)
+```
+
+**Memory address explanation for newcomers:**
+- Hex address `0x20081ffc` is **LARGER** than `0x20081ff8` (compare the last hex digits: `ffc` > `ff8`)
+- **Larger addresses = higher in memory = deeper in the stack**
+- When we PUSH, sp **DECREASES** (goes to a smaller address, moving DOWN on the page)
+- When we POP, sp **INCREASES** (goes to a larger address, moving UP on the page)
+
+The stack pointer dropped 8 bytes: from `0x20082000` to `0x20081ff8` (it went DOWN, to a smaller/lower address).
##### Step 3: Step Over `stdio_init_all`
-Do not step into the library initialization code. Use `ni`:
+Do not step into the library initialization code. Use `ni` to execute it and return:
```gdb
-ni
-disas main
+(gdb) ni
+0x100001e6 15 __asm volatile(
+(gdb) disas main
+Dump of assembler code for function main:
+ 0x100001e0 <+0>: push {r3, lr}
+ 0x100001e2 <+2>: bl 0x10001594
+=> 0x100001e6 <+6>: push {r4, lr}
+ 0x100001e8 <+8>: push {r2, r3, r6}
+ ...
```
-The arrow now points at the first inline instruction: `push {r4, lr}`.
+The arrow now points at `push {r4, lr}`, the first inline assembly instruction.
##### Step 4: Prove the First Inline Push
-Read the registers before saving them:
+Read the registers and stack pointer before the first inline push:
```gdb
-p/x $r4
-p/x $lr
-p/x $sp
+(gdb) p/x $r4
+$3 = 0x100001cc
+(gdb) p/x $lr
+$4 = 0x1000159b
+(gdb) p/x $sp
+$5 = 0x20081ff8
```
-Execute one instruction and examine the new top of the stack:
+Now execute the first inline push:
```gdb
-si
-x/wx $sp
-x/wx $sp+4
+(gdb) si
+0x100001e8 16 "push {r4, lr}\n"
+(gdb) p/x $sp
+$6 = 0x20081ff0
+(gdb) x/wx $sp
+0x20081ff0: 0x100001cc
+(gdb) x/wx $sp+4
+0x20081ff4: 0x1000159b
```
-The values at `[sp]` and `[sp+4]` match the values shown for `r4` and `lr`. This push reduced `sp` by 8 bytes.
+**After first inline push `push {r4, lr}`:**
+- SP = `0x20081ff0` (**new TOP of stack, sp decreased**)
+- `r4` = `0x100001cc` (now saved on stack)
+- `lr` = `0x1000159b` (now saved on stack)
+
+The first push saved:
+```text
+[sp + 4] = 0x1000159b (lr, higher address, visual top)
+[sp] = 0x100001cc (r4, lower address) <- SP <- TOP OF STACK
+```
+
+**Stack layout after first inline push**:
+
+```text
+Address Pointer Value Label
+0x20081ffc ---------- 0x1000018b (lr from prologue — highest address, visual top)
+0x20081ff8 ---------- 0xe000ed08 (r3 from prologue — higher address)
+0x20081ff4 ---------- 0x1000159b (lr — higher address)
+0x20081ff0 <- [sp] 0x100001cc (r4, lowest address) <- SP <- TOP OF STACK
+
+MEMORY ORDER: 0x20081ff0 < 0x20081ff4 < 0x20081ff8 < 0x20081ffc
+ (visual bottom) (visual top)
+ Most recent Least recent
+```
+
+**The stack pointer dropped from `0x20081ff8` to `0x20081ff0` — that's 8 bytes down (toward lower addresses).**
+**The value at `[sp]` (the TOP) is now `0x100001cc` (r4).**
+**Address `0x20081ff0` is SMALLER than `0x20081ff8`, so sp moved DOWN.**
+
##### Step 5: Prove Register-List Ordering
-Read the three registers before executing the deliberately unordered list:
+Read the three registers before executing the deliberately unordered list `push {r3, r2, r6}`:
```gdb
-p/x $r2
-p/x $r3
-p/x $r6
-p/x $sp
+(gdb) p/x $r2
+$18 = 0x200005cc
+(gdb) p/x $r3
+$19 = 0xe000ed08
+(gdb) p/x $r6
+$20 = 0x04f54710
+(gdb) p/x $sp
+$21 = 0x20081ff0
```
-Now execute only that instruction:
+Now execute the second inline push:
```gdb
-si
-x/wx $sp
-x/wx $sp+4
-x/wx $sp+8
+(gdb) si
+0x100001ea <+10>: stmdb sp!, {r9, sl}
+(gdb) p/x $sp
+$22 = 0x20081fe4
+(gdb) x/wx $sp
+0x20081fe4: 0x200005cc
+(gdb) x/wx $sp+4
+0x20081fe8: 0xe000ed08
+(gdb) x/wx $sp+8
+0x20081fec: 0x04f54710
```
-Compare the values from the first three commands with the three words in SRAM:
+The second push saved three registers in **numeric order** despite the source spelling `{r3, r2, r6}`:
+```text
+[sp + 8] = 0x04f54710 (r6, higher address, visual top)
+[sp + 4] = 0xe000ed08 (r3, higher address)
+[sp] = 0x200005cc (r2, lower address) <- SP <- TOP OF STACK
+```
+
+**Stack layout after second inline push** (**lower hex addresses = most recent = TOP**):
```text
-[sp] matches r2
-[sp + 4] matches r3
-[sp + 8] matches r6
+Address Pointer Value Label
+0x20081ffc ---------- 0x1000018b (lr — HIGHEST address, OLDEST data, visual top)
+0x20081ff8 ---------- 0xe000ed08 (r3 — higher address)
+0x20081ff4 ---------- 0x1000159b (lr — higher address)
+0x20081ff0 ---------- 0x100001cc (r4 — higher address)
+0x20081fec ---------- 0x04f54710 (r6 — higher address)
+0x20081fe8 ---------- 0xe000ed08 (r3 — higher address)
+0x20081fe4 <- [sp] 0x200005cc (r2, lowest address) <- SP <- TOP OF STACK
+
+ADDRESS ORDERING: 0x20081fe4 < 0x20081fe8 < ... < 0x20081ffc
+ (visual bottom) (visual top)
+ Hex comparison: fe4 < fe8 < fec < ff0 < ff4 < ff8 < ffc
+ Most recent data at the visual bottom
```
-This is the proof. The source ordered the list as `r3`, `r2`, `r6`, but the stack is laid out by ascending register number. A multi-register push is one CPU instruction, so individual transfers inside that instruction cannot be separately stepped.
+**The stack pointer dropped from `0x20081ff0` to `0x20081fe4` — that's 12 bytes down (three 4-byte registers).**
+**When comparing hex: `0x20081fe4` is SMALLER than `0x20081ff0`, so sp moved to a LOWER address.**
+**The value at `[sp]` (the TOP) is now `0x200005cc` (r2).**
+
+Notice: the source wrote `r3` first, but the CPU pushed `r2` first because `r2` has a lower register number. The encoded register mask is `{r2, r3, r6}`, and the stack layout proves it.
##### Step 6: Prove the High-Register Save
-Read the values and execute one instruction:
+Read the high registers before the `stmdb sp!, {r9, r10}` instruction:
```gdb
-p/x $r9
-p/x $r10
-p/x $sp
-si
-x/wx $sp
-x/wx $sp+4
+(gdb) p/x $r9
+$23 = 0x00000000
+(gdb) p/x $r10
+$24 = 0x10000000
+(gdb) p/x $sp
+$25 = 0x20081fe4
```
-`stmdb sp!, {r9, r10}` moved `sp` down by 8 bytes. The first word equals `r9`; the second equals `r10`.
+Execute the high-register save:
+
+```gdb
+(gdb) si
+0x100001ee <+14>: ldmia.w sp!, {r9, sl}
+(gdb) p/x $sp
+$26 = 0x20081fdc
+(gdb) p/x $r9
+$27 = 0x00000000
+(gdb) p/x $r10
+$28 = 0x10000000
+(gdb) x/wx $sp
+0x20081fdc: 0x00000000
+(gdb) x/wx $sp+4
+0x20081fe0: 0x10000000
+(gdb) x/wx $sp+8
+0x20081fe4: 0x200005cc
+(gdb) x/wx $sp+12
+0x20081fe8: 0xe000ed08
+(gdb) x/wx $sp+16
+0x20081fec: 0x04f54710
+(gdb) x/wx $sp+20
+0x20081ff0: 0x100001cc
+(gdb) x/wx $sp+24
+0x20081ff4: 0x1000159b
+(gdb) x/wx $sp+28
+0x20081ff8: 0xe000ed08
+```
+
+**After high-register save `stmdb sp!, {r9, r10}`:**
+- SP = `0x20081fdc` (**new TOP of stack, sp decreased further**)
+- `r9` = `0x00000000` (now saved on stack)
+- `r10` = `0x10000000` (now saved on stack)
+
+The `stmdb sp!, {r9, r10}` instruction saved:
+```text
+[sp + 4] = 0x10000000 (r10, higher address, visual top)
+[sp] = 0x00000000 (r9, lower address) <- SP <- TOP OF STACK
+```
+
+**The stack pointer dropped from `0x20081fe4` to `0x20081fdc` — that's 8 more bytes down.**
+**The value at `[sp]` (the TOP) is now `0x00000000` (r9).**
+**This is the DEEPEST point of the stack during inline assembly.**
+
+```text
+Address Pointer Value Label
+0x20081ff8 ---------- 0xe000ed08 (saved prologue r3, highest address, visual top)
+0x20081ff4 ---------- 0x1000159b (lr, higher address)
+0x20081ff0 ---------- 0x100001cc (r4, higher address)
+0x20081fec ---------- 0x04f54710 (r6, higher address)
+0x20081fe8 ---------- 0xe000ed08 (r3, higher address)
+0x20081fe4 ---------- 0x200005cc (r2, higher address)
+0x20081fe0 ---------- 0x10000000 (r10, higher address)
+0x20081fdc <- [sp] 0x00000000 (r9, lowest address) <- SP <- TOP OF STACK
+```
##### Step 7: Watch the Restores
-Execute and inspect each restore separately:
+At this point, the stack is at maximum depth. Now execute the restore instructions one by one:
+
+**Restore 1: ldmia sp!, {r9, r10}**
```gdb
-si
-p/x $sp
-x/3wx $sp
-
-si
-p/x $sp
-x/2wx $sp
-
-si
-p/x $sp
+(gdb) si
+0x100001f2 <+18>: pop {r2, r3, r6}
+(gdb) p/x $sp
+$29 = 0x20081fe4
+(gdb) p/x $r9
+$30 = 0x00000000
+(gdb) p/x $r10
+$31 = 0x10000000
```
-The three instructions raise `sp` by 8, 12, and 8 bytes respectively. The final value is the same stack pointer you saw before the first inline push.
+`ldmia sp!` restored `r9` and `r10` from the stack and raised `sp` by 8 bytes (from `0x20081fdc` to `0x20081fe4`).
+**SP is now `0x20081fe4`; `[sp]` contains r2, so `SP <- TOP OF STACK` at the next group.**
+
+**Restore 2: pop {r2, r3, r6}**
+
+```gdb
+(gdb) si
+0x100001f4 <+20>: ldmia.w sp!, {r4, lr}
+(gdb) p/x $sp
+$32 = 0x20081ff0
+(gdb) p/x $r2
+$33 = 0x200005cc
+(gdb) p/x $r3
+$34 = 0xe000ed08
+(gdb) p/x $r6
+$35 = 0x04f54710
+```
+
+`pop {r2, r3, r6}` restored the three registers from SRAM and raised `sp` by 12 bytes (from `0x20081fe4` to `0x20081ff0`).
+**SP is now `0x20081ff0`; `[sp]` contains r4, so `SP <- TOP OF STACK` at the final group.**
+
+**Restore 3: ldmia.w sp!, {r4, lr}**
+
+```gdb
+(gdb) si
+0x100001f8 <+24>: b.n 0x100001e6
+(gdb) p/x $sp
+$36 = 0x20081ff8
+(gdb) p/x $r4
+$37 = 0x100001cc
+(gdb) p/x $lr
+$38 = 0x1000159b
+```
+
+`ldmia.w sp!, {r4, lr}` restored `r4` and `lr` from SRAM and raised `sp` by 8 bytes (from `0x20081ff0` to `0x20081ff8`).
+**SP is now `0x20081ff8`; `[sp]` contains the saved prologue r3, so `SP <- TOP OF STACK` for the remaining prologue stack data.**
+
+**Result:** After all three restore instructions, `sp` is back at `0x20081ff8`, exactly where it was before the inline assembly block started. The loop branches back to `push {r4, lr}` at address `0x100001e6` and repeats forever without consuming stack space.
### Understanding the Stack Diagram
@@ -435,7 +642,7 @@ At the deepest point, after `stmdb sp!, {r9, r10}`, the inline assembly has save
```text
Before inline assembly: At maximum inline stack depth:
-old SP <- SP old SP
+old SP <- SP old SP
[old SP - 4] lr
[old SP - 8] r4
[old SP - 12] r6
@@ -464,22 +671,22 @@ The restoration sequence removes the top group first: `r9/r10`, then `r2/r3/r6`,
```text
+-----------------------------------------------------+
| 1. push {r3, lr} |
-| Compiler saves its prologue registers |
+| Compiler saves its prologue registers |
+-----------------------------------------------------+
-| 2. bl stdio_init_all |
-| Initialize standard I/O |
+| 2. bl stdio_init_all |
+| Initialize standard I/O |
+-----------------------------------------------------+
| 3. push {r4, lr} |
-| Save the first inline group |
+| Save the first inline group |
+-----------------------------------------------------+
| 4. push {r3, r2, r6} |
-| Source order differs from stack-memory order |
+| Source order differs from stack-memory order |
+-----------------------------------------------------+
-| 5. stmdb / ldmia / pop / pop |
-| Save and restore all groups |
+| 5. stmdb / ldmia / pop / pop |
+| Save and restore all groups |
+-----------------------------------------------------+
-| 6. b.n main+6 |
-| Repeat with the original stack pointer |
+| 6. b.n main+6 |
+| Repeat with the original stack pointer |
+-----------------------------------------------------+
```
diff --git a/WEEK01/WEEK01a.pdf b/WEEK01/WEEK01a.pdf
index f22332f..b0e083e 100644
Binary files a/WEEK01/WEEK01a.pdf and b/WEEK01/WEEK01a.pdf differ