Update WEEK06
@@ -1,6 +1,6 @@
|
||||
# 📘 Week 6: Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics
|
||||
# Week 6: Static Variables in Embedded Systems: Debugging and Hacking Static Variables w/ GPIO Input Basics
|
||||
|
||||
## 🎯 What You'll Learn This Week
|
||||
## What You'll Learn This Week
|
||||
|
||||
By the end of this tutorial, you will be able to:
|
||||
- Understand the difference between regular (automatic) variables and static variables
|
||||
@@ -30,18 +30,18 @@ Think of it like this:
|
||||
| |
|
||||
| REGULAR (automatic): |
|
||||
| +------------------------------------------------------------+ |
|
||||
| | Loop 1: Create -> Set to 42 -> Increment to 43 -> Destroy | |
|
||||
| | Loop 2: Create -> Set to 42 -> Increment to 43 -> Destroy | |
|
||||
| | Loop 3: Create -> Set to 42 -> Increment to 43 -> Destroy | |
|
||||
| | Result: Always appears as 42! | |
|
||||
| | Loop 1: Create -> Set to 42 -> Increment to 43 -> Destroy |
|
||||
| | Loop 2: Create -> Set to 42 -> Increment to 43 -> Destroy |
|
||||
| | Loop 3: Create -> Set to 42 -> Increment to 43 -> Destroy |
|
||||
| | Result: Always appears as 42! |
|
||||
| +------------------------------------------------------------+ |
|
||||
| |
|
||||
| STATIC: |
|
||||
| +------------------------------------------------------------+ |
|
||||
| | Loop 1: Already exists -> Read 42 -> Increment -> Store 43 | |
|
||||
| | Loop 2: Already exists -> Read 43 -> Increment -> Store 44 | |
|
||||
| | Loop 3: Already exists -> Read 44 -> Increment -> Store 45 | |
|
||||
| | Result: Keeps incrementing! | |
|
||||
| | Loop 1: Already exists -> Read 42 -> Increment -> Store 43 |
|
||||
| | Loop 2: Already exists -> Read 43 -> Increment -> Store 44 |
|
||||
| | Loop 3: Already exists -> Read 44 -> Increment -> Store 45 |
|
||||
| | Result: Keeps incrementing! |
|
||||
| +------------------------------------------------------------+ |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
@@ -74,19 +74,19 @@ Different types of variables are stored in different memory locations:
|
||||
| Memory Layout |
|
||||
| |
|
||||
| +-------------------+ High Address (0x20082000) |
|
||||
| | STACK | ?? Automatic/local variables |
|
||||
| | (grows down) | Created/destroyed per function |
|
||||
| | STACK | ?? Automatic/local variables |
|
||||
| | (grows down) | Created/destroyed per function |
|
||||
| +-------------------+ |
|
||||
| | | |
|
||||
| | (free space) | |
|
||||
| | | |
|
||||
| +-------------------+ |
|
||||
| | HEAP | ?? Dynamic allocation (malloc/free) |
|
||||
| | HEAP | ?? Dynamic allocation (malloc/free) |
|
||||
| | (grows up) | |
|
||||
| +-------------------+ |
|
||||
| | .bss section | ?? Uninitialized static/global vars |
|
||||
| | .bss section | ?? Uninitialized static/global vars |
|
||||
| +-------------------+ |
|
||||
| | .data section | ?? Initialized static/global vars |
|
||||
| | .data section | ?? Initialized static/global vars |
|
||||
| +-------------------+ Low Address (0x20000000) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
@@ -174,7 +174,7 @@ The Pico 2 has **internal** pull resistors that you can enable with software - n
|
||||
| +------? GPIO 15 (reads HIGH normally) |
|
||||
| | |
|
||||
| +-+-+ |
|
||||
| |BTN| ?? Button connects GPIO to GND when pressed |
|
||||
| |BTN| ?? Button connects GPIO to GND when pressed |
|
||||
| +-+-+ |
|
||||
| | |
|
||||
| GND |
|
||||
@@ -312,7 +312,7 @@ Embedded-Hacking/
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Part 5: Hands-On Tutorial - Static Variables and GPIO Input
|
||||
## Part 5: Hands-On Tutorial - Static Variables and GPIO Input
|
||||
|
||||
### Step 1: Review the Source Code
|
||||
|
||||
@@ -400,10 +400,10 @@ static_fav_num: 45
|
||||
### Step 4: Test the Button
|
||||
|
||||
Now test the button behavior:
|
||||
- **Button NOT pressed:** LED should be ON (because of the inverted logic)
|
||||
- **Button PRESSED:** LED should turn OFF
|
||||
- **Button NOT pressed:** LED should be OFF
|
||||
- **Button PRESSED:** LED should turn ON
|
||||
|
||||
Wait... that seems backwards from what you'd expect! That's because of the pull-up resistor and the ternary operator. We'll hack this later to make it more intuitive!
|
||||
That may feel backwards at first glance, but it matches the pull-up + ternary logic in the code. We'll hack this later to make the behavior more intuitive.
|
||||
|
||||
### Step 5: Watch for Overflow
|
||||
|
||||
@@ -422,7 +422,7 @@ This demonstrates unsigned integer overflow!
|
||||
|
||||
---
|
||||
|
||||
## 🐛 Part 6: Debugging with GDB (Dynamic Analysis)
|
||||
## Part 6: Debugging with GDB (Dynamic Analysis)
|
||||
|
||||
> ? **REVIEW:** This setup is identical to previous weeks. If you need a refresher on OpenOCD and GDB connection, refer back to Week 3 Part 6.
|
||||
|
||||
@@ -430,24 +430,20 @@ This demonstrates unsigned integer overflow!
|
||||
|
||||
**Terminal 1 - Start OpenOCD:**
|
||||
|
||||
```powershell
|
||||
openocd ^
|
||||
-s "C:\Users\assem.KEVINTHOMAS\.pico-sdk\openocd\0.12.0+dev\scripts" ^
|
||||
-f interface/cmsis-dap.cfg ^
|
||||
-f target/rp2350.cfg ^
|
||||
-c "adapter speed 5000"
|
||||
```cmd
|
||||
openocd -s "%USERPROFILE%\.pico-sdk\openocd\0.12.0+dev\scripts" -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"
|
||||
```
|
||||
|
||||
**Terminal 2 - Start GDB:**
|
||||
|
||||
```powershell
|
||||
```cmd
|
||||
arm-none-eabi-gdb build\0x0014_static-variables.elf
|
||||
```
|
||||
|
||||
**Connect to target:**
|
||||
|
||||
```gdb
|
||||
(gdb) target remote :3333
|
||||
(gdb) target extended-remote :3333
|
||||
(gdb) monitor reset halt
|
||||
```
|
||||
|
||||
@@ -462,44 +458,45 @@ x/38i 0x10000234
|
||||
You should see output like:
|
||||
|
||||
```
|
||||
0x10000234 <+0>: push {r4, lr}
|
||||
0x10000236 <+2>: bl 0x10003014 <stdio_init_all>
|
||||
0x1000023a <+6>: movs r0, #15
|
||||
0x1000023c <+8>: bl 0x10000300 <gpio_init>
|
||||
0x10000240 <+12>: movs r0, #15
|
||||
0x10000242 <+14>: mov.w r3, #0
|
||||
0x10000246 <+18>: mcrr 0, 4, r0, r3, cr4
|
||||
0x1000024a <+22>: movs r2, #0
|
||||
0x1000024c <+24>: movs r1, #1
|
||||
0x1000024e <+26>: bl 0x100002d8 <gpio_set_pulls>
|
||||
0x10000252 <+30>: movs r0, #16
|
||||
0x10000254 <+32>: bl 0x10000300 <gpio_init>
|
||||
0x10000258 <+36>: movs r3, #16
|
||||
0x1000025a <+38>: mov.w r2, #1
|
||||
0x1000025e <+42>: mcrr 0, 4, r3, r2, cr4
|
||||
0x10000262 <+46>: ldr r4, [pc, #44] @ (0x10000290 <main+92>)
|
||||
0x10000264 <+48>: movs r1, #42 @ 0x2a
|
||||
0x10000266 <+50>: ldr r0, [pc, #44] @ (0x10000294 <main+96>)
|
||||
0x10000268 <+52>: bl 0x100031a4 <__wrap_printf>
|
||||
0x1000026c <+56>: ldrb r1, [r4, #0]
|
||||
0x1000026e <+58>: ldr r0, [pc, #40] @ (0x10000298 <main+100>)
|
||||
0x10000270 <+60>: bl 0x100031a4 <__wrap_printf>
|
||||
0x10000274 <+64>: mov.w r1, #3489660928 @ 0xd0000000
|
||||
0x10000278 <+68>: ldrb r3, [r4, #0]
|
||||
0x1000027a <+70>: movs r2, #16
|
||||
0x1000027c <+72>: adds r3, #1
|
||||
0x1000027e <+74>: strb r3, [r4, #0]
|
||||
0x10000280 <+76>: ldr r3, [r1, #4]
|
||||
0x10000282 <+78>: ubfx r3, r3, #15, #1
|
||||
0x10000286 <+82>: eor.w r3, r3, #1
|
||||
0x1000028a <+86>: mcrr 0, 4, r2, r3, cr0
|
||||
0x1000028e <+90>: b.n 0x10000264 <main+48>
|
||||
0x10000290 <+92>: lsls r0, r5, #22
|
||||
0x10000292 <+94>: movs r0, #0
|
||||
0x10000294 <+96>: adds r5, #96 @ 0x60
|
||||
0x10000296 <+98>: asrs r0, r0, #32
|
||||
0x10000298 <+100>: adds r5, #120 @ 0x78
|
||||
0x1000029a <+102>: asrs r0, r0, #32
|
||||
(gdb) x/38i 0x10000234
|
||||
0x10000234 <main>: push {r4, lr}
|
||||
0x10000236 <main+2>: bl 0x10003014 <stdio_init_all>
|
||||
0x1000023a <main+6>: movs r0, #15
|
||||
0x1000023c <main+8>: bl 0x10000300 <gpio_init>
|
||||
0x10000240 <main+12>: movs r0, #15
|
||||
0x10000242 <main+14>: mov.w r3, #0
|
||||
0x10000246 <main+18>: mcrr 0, 4, r0, r3, cr4
|
||||
0x1000024a <main+22>: movs r2, #0
|
||||
0x1000024c <main+24>: movs r1, #1
|
||||
0x1000024e <main+26>: bl 0x100002d8 <gpio_set_pulls>
|
||||
0x10000252 <main+30>: movs r0, #16
|
||||
0x10000254 <main+32>: bl 0x10000300 <gpio_init>
|
||||
0x10000258 <main+36>: movs r3, #16
|
||||
0x1000025a <main+38>: mov.w r2, #1
|
||||
0x1000025e <main+42>: mcrr 0, 4, r3, r2, cr4
|
||||
0x10000262 <main+46>: ldr r4, [pc, #44] @ (0x10000290 <main+92>)
|
||||
0x10000264 <main+48>: movs r1, #42 @ 0x2a
|
||||
0x10000266 <main+50>: ldr r0, [pc, #44] @ (0x10000294 <main+96>)
|
||||
0x10000268 <main+52>: bl 0x100031a4 <__wrap_printf>
|
||||
0x1000026c <main+56>: ldrb r1, [r4, #0]
|
||||
0x1000026e <main+58>: ldr r0, [pc, #40] @ (0x10000298 <main+100>)
|
||||
0x10000270 <main+60>: bl 0x100031a4 <__wrap_printf>
|
||||
0x10000274 <main+64>: mov.w r1, #3489660928 @ 0xd0000000
|
||||
0x10000278 <main+68>: ldrb r3, [r4, #0]
|
||||
0x1000027a <main+70>: movs r2, #16
|
||||
0x1000027c <main+72>: adds r3, #1
|
||||
0x1000027e <main+74>: strb r3, [r4, #0]
|
||||
0x10000280 <main+76>: ldr r3, [r1, #4]
|
||||
0x10000282 <main+78>: ubfx r3, r3, #15, #1
|
||||
0x10000286 <main+82>: eor.w r3, r3, #1
|
||||
0x1000028a <main+86>: mcrr 0, 4, r2, r3, cr0
|
||||
0x1000028e <main+90>: b.n 0x10000264 <main+48>
|
||||
0x10000290 <main+92>: lsls r0, r5, #22
|
||||
0x10000292 <main+94>: movs r0, #0
|
||||
0x10000294 <main+96>: adds r5, #96 @ 0x60
|
||||
0x10000296 <main+98>: asrs r0, r0, #32
|
||||
0x10000298 <main+100>: adds r5, #120 @ 0x78
|
||||
0x1000029a <main+102>: asrs r0, r0, #32
|
||||
```
|
||||
|
||||
### Step 7: Set a Breakpoint at Main
|
||||
@@ -509,26 +506,28 @@ b *0x10000234
|
||||
c
|
||||
```
|
||||
|
||||
GDB responds:
|
||||
```
|
||||
Breakpoint 1 at 0x10000234: file C:/Users/assem.KEVINTHOMAS/OneDrive/Documents/Embedded-Hacking/0x0014_static-variables/0x0014_static-variables.c, line 5.
|
||||
Note: automatically using hardware breakpoints for read-only addresses.
|
||||
(gdb) c
|
||||
Continuing.
|
||||
|
||||
Thread 1 "rp2350.cm0" hit Breakpoint 1, main ()
|
||||
at C:/Users/assem.KEVINTHOMAS/OneDrive/Documents/Embedded-Hacking/0x0014_static-variables/0x0014_static-variables.c:5
|
||||
5 stdio_init_all();
|
||||
```
|
||||
|
||||
> **Note:** If GDB says `The program is not being run.` when you type `c`, the target hasn't been started yet. Use `monitor reset halt` first, then `c` to continue to your breakpoint.
|
||||
|
||||
### Step 8: Examine the Static Variable Location
|
||||
|
||||
Static variables live at fixed RAM addresses. But how do we find that address? Look at the first instruction in the disassembly from Step 6:
|
||||
Static variables live at fixed RAM addresses. But how do we find that address? Look at `0x10000262` in the disassembly from Step 6:
|
||||
|
||||
```
|
||||
0x10000262: ldr r4, [pc, #44] @ (0x10000290 <main+92>)
|
||||
(gdb) x/16i 0x10000234
|
||||
=> 0x10000234 <main>: push {r4, lr}
|
||||
0x10000236 <main+2>: bl 0x10003014 <stdio_init_all>
|
||||
0x1000023a <main+6>: movs r0, #15
|
||||
0x1000023c <main+8>: bl 0x10000300 <gpio_init>
|
||||
0x10000240 <main+12>: movs r0, #15
|
||||
0x10000242 <main+14>: mov.w r3, #0
|
||||
0x10000246 <main+18>: mcrr 0, 4, r0, r3, cr4
|
||||
0x1000024a <main+22>: movs r2, #0
|
||||
0x1000024c <main+24>: movs r1, #1
|
||||
0x1000024e <main+26>: bl 0x100002d8 <gpio_set_pulls>
|
||||
0x10000252 <main+30>: movs r0, #16
|
||||
0x10000254 <main+32>: bl 0x10000300 <gpio_init>
|
||||
0x10000258 <main+36>: movs r3, #16
|
||||
0x1000025a <main+38>: mov.w r2, #1
|
||||
0x1000025e <main+42>: mcrr 0, 4, r3, r2, cr4
|
||||
0x10000262 <main+46>: ldr r4, [pc, #44] @ (0x10000290 <main+92>)
|
||||
```
|
||||
|
||||
This loads `r4` from the **literal pool** at address `0x10000290`. The literal pool stores constants that are too large for immediate encoding - in this case, a 32-bit RAM address. Let's examine what's stored there:
|
||||
@@ -540,38 +539,259 @@ This loads `r4` from the **literal pool** at address `0x10000290`. The literal p
|
||||
|
||||
That's `0x200005a8` - the RAM address of `static_fav_num`! The compiler placed this address in the literal pool because it can't encode a full 32-bit address in a single Thumb instruction.
|
||||
|
||||
> **Common confusion three things that trip people up here:**
|
||||
>
|
||||
> **1. GDB shows `<striped_spin_lock_num>` instead of `<static_fav_num>`.**
|
||||
> `static_fav_num` is a function-local static, so it does not appear in GDB's global symbol table. GDB labels the address with the nearest *named* global symbol it can find in this case an SDK-internal spin-lock variable that happens to be nearby. The address `0x200005a8` is still correct; the label is just GDB's best guess at a name.
|
||||
```gdb
|
||||
(gdb) x/x 0x200005a8
|
||||
0x200005a8 <striped_spin_lock_num>: 0x0000122a
|
||||
```
|
||||
>
|
||||
> **2. `x/x 0x200005a8` shows `0x0000122a`, not `0x0000002a` (42).**
|
||||
> `x/x` reads a **4-byte word** (32 bits). `static_fav_num` is a `uint8_t` only **1 byte**. The low byte of `0x0000122a` is `0x2a` = 42. That *is* the variable. The upper bytes belong to whatever happens to be in adjacent RAM. To read exactly one byte and see `42`, use:
|
||||
```gdb
|
||||
(gdb) x/1ub 0x200005a8
|
||||
0x200005a8 <striped_spin_lock_num>: 42
|
||||
```
|
||||
>
|
||||
> **3. `x/x *0x200005a8` shows junk at address `0x122a`.**
|
||||
> The `*` is a pointer dereference. GDB first reads the 4-byte word at `0x200005a8` (= `0x0000122a`), then treats that *value* as a new address and reads from `0x0000122a`. You are asking GDB to follow a pointer that was never meant to be a pointer the result is meaningless. Drop the `*`: use `x/1ub 0x200005a8` to read the variable's value directly.
|
||||
|
||||
> Tip: **Why did the disassembly at `0x10000290` show `lsls r0, r5, #22` instead?** Because `x/i` (disassemble) interprets raw data as instructions. The bytes `A8 05 00 20` at that address are the little-endian encoding of `0x200005A8`, but GDB's disassembler doesn't know it's data - it tries to decode it as a Thumb instruction. Using `x/wx` (examine as word) shows the actual value.
|
||||
|
||||
### Step 9: Step Through the Loop
|
||||
|
||||
Set a breakpoint at the start of the loop and step through:
|
||||
The loop body starts at `0x10000264`. Set a breakpoint there and continue:
|
||||
|
||||
```gdb
|
||||
(gdb) b *0x10000264
|
||||
(gdb) c
|
||||
(gdb) x/i $pc
|
||||
=> 0x10000264 <main+48>: movs r1, #42 @ 0x2a
|
||||
```
|
||||
|
||||
Now use `si` (step instruction) to execute one instruction at a time:
|
||||
GDB will stop at `movs r1, #42` that is the compiler's constant for `regular_fav_num`. Let's set a breakpoint and continue at `0x10000278`.
|
||||
|
||||
```gdb
|
||||
(gdb) si
|
||||
(gdb) b *0x10000278
|
||||
(gdb) c
|
||||
(gdb) x/i $pc
|
||||
=> 0x10000278 <main+68>: ldrb r3, [r4, #0]
|
||||
```
|
||||
|
||||
Watch how the static variable gets loaded (`ldrb`), incremented (`adds`), and stored back (`strb`).
|
||||
This is where the static variable is actually manipulated:
|
||||
|
||||
```gdb
|
||||
(gdb) x/4i $pc
|
||||
=> 0x10000278 <main+68>: ldrb r3, [r4, #0] <- load static_fav_num from RAM into r3
|
||||
0x1000027a <main+70>: movs r2, #16 <- load LED pin number (16) into r2 for later
|
||||
0x1000027c <main+72>: adds r3, #1 <- increment r3 by 1
|
||||
0x1000027e <main+74>: strb r3, [r4, #0] <- store incremented value back to RAM
|
||||
```
|
||||
|
||||
Confirm what `r4` actually contains right now:
|
||||
|
||||
```gdb
|
||||
(gdb) x/x $r4
|
||||
0x200005a8 <striped_spin_lock_num>: 0x2a
|
||||
```
|
||||
|
||||
`r4` is `0x200005a8`, a RAM address. The value at that address is `0x2a` (42 in decimal), which is the current value of `static_fav_num`. After `adds r3, #1` and `strb r3, [r4, #0]` execute, examining `r4` again will show `0x0000002b` (43).
|
||||
|
||||
**What is the literal pool?**
|
||||
|
||||
A Thumb `ldr` instruction is only 16 or 32 bits wide. There is no room inside those bits to encode a full 32-bit constant like `0x200005a8`. To solve this, the compiler collects all such large constants and writes them into a small block of **raw data** embedded directly in the flash image this block is called a **literal pool** (also called a constant pool).
|
||||
|
||||
**There is not one literal pool per flash, there is (at least) one per function.** Every function that references large constants gets its own pool appended to its code. A large function can have several pools scattered through it wherever the compiler decides to emit them. Each pool is purely data; the CPU must never try to execute it.
|
||||
|
||||
**Where exactly is a literal pool placed?** Always **after an unconditional branch**, never before or in the middle of a straight-line code path. This is by design: the CPU falls through code sequentially, so the pool must be unreachable by fall-through. In our case the pool sits at `0x10000290`, directly after the `b.n 0x10000264` branch at `0x1000028e` that closes the `while (true)` loop:
|
||||
|
||||
```
|
||||
0x1000028e: b.n 0x10000264 <- unconditional branch back to loop top
|
||||
0x10000290: [literal pool] <- CPU never reaches here by fall-through
|
||||
```
|
||||
|
||||
**Why does the pool have to be nearby?** The `ldr rN, [pc, #offset]` instruction encodes the offset in a limited number of bits. In standard Thumb the maximum reach is **1020 bytes** from the instruction. If the function is long enough that the end is out of range, the assembler emits an intermediate pool mid-function after the next unconditional branch it can find. This is in the ARM v8-M Architecture Reference Manual p. 672.
|
||||
|
||||
**How the load works in our function:** At `0x10000262` the compiler emits:
|
||||
|
||||
```
|
||||
ldr r4, [pc, #44] @ (0x10000290)
|
||||
```
|
||||
|
||||
On ARM, `PC` reads as the address of the instruction **plus 4** during execution. So the effective address is `0x10000262 + 4 + 44 = 0x10000290`. That word in the pool contains `0x200005a8`, the RAM address of `static_fav_num`. The pool is also where the `printf` format-string pointers live (the other `ldr` instructions you saw in the disassembly).
|
||||
|
||||
```
|
||||
Flash (read-only)
|
||||
+-------------------------------------------+ RAM
|
||||
| 0x10000262: ldr r4, [pc, #44] | +------------------+
|
||||
| ...loop body... | | 0x200005a8: 42 | <- static_fav_num
|
||||
| 0x1000028e: b.n 0x10000264 (end of loop) | +------------------+
|
||||
+------- literal pool (data, not code) -----+ ^
|
||||
| 0x10000290: 0x200005a8 --------------------+----------------+
|
||||
| 0x10000294: ptr to "regular_fav_num: %d" | r4 holds this address
|
||||
| 0x10000298: ptr to "static_fav_num: %d" |
|
||||
+------- next function ---------------------+
|
||||
| 0x1000029c: push {r4} |
|
||||
+-------------------------------------------+
|
||||
```
|
||||
|
||||
You can see this directly. Run `x/10i 0x1000028e` in GDB and you will get exactly this:
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x1000028e
|
||||
(gdb) x/10i 0x1000028e
|
||||
0x1000028e <main+90>: b.n 0x10000264 <main+48> <- unconditional branch, loop top
|
||||
0x10000290 <main+92>: lsls r0, r5, #22 <-+
|
||||
0x10000292 <main+94>: movs r0, #0 <-+-- word 1: 0x200005a8 (fixed RAM addr static_fav_num)
|
||||
0x10000294 <main+96>: adds r5, #96 @ 0x60 <-+
|
||||
0x10000296 <main+98>: asrs r0, r0, #32 <-+-- word 2: 0x10004b60 (flash addr regular_fav_num text)
|
||||
0x10000298 <main+100>: adds r5, #120 <-+
|
||||
0x1000029a <main+102>: asrs r0, r0, #32 <-+-- word 3: 0x10004b78 (flash addr static_fav_num text)
|
||||
```
|
||||
|
||||
`0x10000290` - `0x1000029b` is the literal pool 12 bytes, 3 32-bit words. GDB's `x/i` (disassemble) has no idea those bytes are data, so it blindly decodes them as Thumb instructions and produces nonsense (`lsls r0, r5, #22`, etc.). The giveaway that you have entered pool territory is always the same: **garbled, implausible instructions immediately after an unconditional branch**. Use `x/wx` to read those addresses as data and you get the real values:
|
||||
|
||||
```gdb
|
||||
(gdb) x/3wx 0x10000290
|
||||
0x10000290 <main+92>: 0x200005a8 0x10003560 0x10003578
|
||||
```
|
||||
|
||||
```gdb
|
||||
(gdb) x/1ub 0x200005a8
|
||||
0x200005a8 <striped_spin_lock_num>: 42
|
||||
```
|
||||
- `0x200005a8` RAM address of `static_fav_num`, lives in the **`.data` section** (initialized static RAM, `0x20000000``0x200xxxxx`). It is `.data` and not `.bss` because the variable has an explicit initializer (`= 42`). `.bss` is for variables that are zero-initialized or have no initializer at all.
|
||||
|
||||
```gdb
|
||||
(gdb) x/s 0x10003560
|
||||
0x10003560: "regular_fav_num: %d\r\n"
|
||||
```
|
||||
- `0x10003560` flash address of the `"regular_fav_num: %d\r\n"` string literal, lives in the **`.rodata` section** (read-only data) inside flash (`0x10000000`+). String literals are constants baked into the binary at compile time they never change and never move, so they stay in flash.
|
||||
|
||||
```gdb
|
||||
(gdb) x/s 0x10003578
|
||||
0x10003578: "static_fav_num: %d\r\n"
|
||||
- `0x10003578` flash address of the `"static_fav_num: %d\r\n"` string literal, also in **`.rodata`** in flash for the same reason.
|
||||
|
||||
So the pool contains addresses into three different regions: RAM `.data` (the static variable), and flash `.rodata` (both format strings). Only the RAM address needed to be in the pool, the flash addresses could in principle be reached other ways, but they are also too large to encode as 16-bit immediates, so they go in the pool too.
|
||||
|
||||
**Why `.data` and not `.bss`?** The distinction matters:
|
||||
|
||||
| Section | What goes here | Example declarations | Initial value stored in flash? |
|
||||
|---------|---------------|----------------------|-------------------------------|
|
||||
| `.data` | Any static-duration variable with a **non-zero initializer** | `static uint8_t x = 42;` (inside a function) | Yes the initial value lives in flash; startup copies it to RAM |
|
||||
| `.data` | Same rule applies to **global** variables with non-zero initializers | `uint8_t g = 10;` (outside all functions) | Yes same startup copy |
|
||||
| `.bss` | Any static-duration variable with **no initializer or zero initializer** | `static uint8_t x;` or `static uint8_t x = 0;` | No startup just zeroes the RAM range; no flash copy needed |
|
||||
| `.bss` | Same rule for **global** variables that are zero/uninitialized | `uint8_t g;` or `uint8_t g = 0;` (outside functions) | No same zero-fill at startup |
|
||||
|
||||
The rule is not about `static` specifically it is about **lifetime and initial value**. Any variable whose lifetime spans the whole program (static locals, globals) goes into `.data` or `.bss`. The `static` keyword inside a function just forces that lifetime. A global variable without `static` has the same lifetime and follows the same rule.
|
||||
|
||||
`static_fav_num = 42` has an explicit non-zero initializer, so the linker puts it in `.data`. The startup code copies the initial value `42` from flash into RAM address `0x200005a8` before `main()` runs. If it had been `static uint8_t static_fav_num;` (no initializer), the linker would put it in `.bss` instead and the startup code would zero that RAM region no flash copy needed.
|
||||
|
||||
**Why is there no pool entry for the address of `regular_fav_num`?**
|
||||
|
||||
Because `regular_fav_num` is an **automatic (stack) variable** it has no fixed address. Automatic variables are allocated on the call stack at runtime, relative to the current stack pointer (`sp`). Their address changes every time the function runs and is different on every call. There is no constant 32-bit address to put in a pool.
|
||||
|
||||
In this specific case the compiler went even further: it **never gave `regular_fav_num` a stack slot at all**. The compiler saw that the value is always `42` when printed, so it baked the constant `42` directly into the `movs r1, #42` instruction. The variable lives only in a register at the moment it is needed — no stack space reserved, no pool entry, no load-store cycle.
|
||||
|
||||
**You can prove this with three GDB checks:**
|
||||
|
||||
**Proof 1 `info locals` shows the value came from a register, not a stack slot:**
|
||||
|
||||
```gdb
|
||||
(gdb) b *0x10000264
|
||||
(gdb) c
|
||||
(gdb) info locals
|
||||
regular_fav_num = 42 '*'
|
||||
static_fav_num = 42 '*'
|
||||
BUTTON_GPIO = 15
|
||||
LED_GPIO = 16
|
||||
pressed = <optimized out>
|
||||
```
|
||||
|
||||
The `'*'` suffix after `42` means GDB retrieved the value from a **register** (specifically `r1`, which holds `42` at this point), not from a stack slot. The variable has no fixed memory address — GDB can report its current value only because the right register happens to hold it right now. Notice that `pressed` is the one showing `<optimized out>` — the compiler removed it from tracking entirely because its value is never needed after the ternary expression.
|
||||
|
||||
**Proof 2 The function prologue allocates no stack space for locals:**
|
||||
|
||||
```gdb
|
||||
(gdb) x/2i 0x10000234
|
||||
0x10000234 <main>: push {r4, lr}
|
||||
0x10000236 <main+2>: bl 0x10003014 <stdio_init_all>
|
||||
```
|
||||
|
||||
The very first instruction is `push {r4, lr}`, that saves `r4` (a callee-saved register) and `lr` (return address). There is **no** `sub sp, #N` instruction after it. On ARM, allocating stack space for local variables requires subtracting from `sp` to reserve room. If `regular_fav_num` lived on the stack, there would be a `sub sp, #4` (or similar) here. There isn't, so no stack slot was ever created.
|
||||
|
||||
**Proof 3 The loop body contains no store to the stack for `regular_fav_num`:**
|
||||
|
||||
```gdb
|
||||
(gdb) x/6i 0x10000264
|
||||
=> 0x10000264 <main+48>: movs r1, #42 @ 0x2a
|
||||
// constant 42 baked directly into instruction
|
||||
0x10000266 <main+50>: ldr r0, [pc, #44] @ (0x10000294 <main+96>)
|
||||
// load format string address from pool
|
||||
0x10000268 <main+52>: bl 0x100031a4 <__wrap_printf>
|
||||
// call printf
|
||||
0x1000026c <main+56>: ldrb r1, [r4, #0]
|
||||
// load static_fav_num from RAM
|
||||
0x1000026e <main+58>: ldr r0, [pc, #40] @ (0x10000298 <main+100>)
|
||||
// load format string address from pool
|
||||
0x10000270 <main+60>: bl 0x100031a4 <__wrap_printf>
|
||||
call printf
|
||||
```
|
||||
|
||||
For `regular_fav_num`, the value `42` goes straight into `r1` via `movs`, it is never written to memory and never read back from memory. There is no `strb r1, [sp, #N]` storing it to the stack, and no `ldrb r1, [sp, #N]` loading it back. The variable exists only in the source code. In the binary it is just a number in an instruction encoding.
|
||||
|
||||
`static_fav_num` is the exact opposite. It lives in the `.data` section of RAM, a fixed, known address (`0x200005a8`) that is set at link time and never changes for the life of the program. That fixed address is exactly the kind of value that cannot fit in a 16-bit Thumb instruction, so the linker writes it into the literal pool and the CPU fetches it with `ldr r4, [pc, #44]`.
|
||||
|
||||
> **IMPORTANT:** Static variables are **not** on the heap. The heap is for dynamic memory (`malloc`/`free`), memory whose lifetime is controlled explicitly at runtime. Static and global variables live in the `.data` section (if initialized) or `.bss` section (if zero/uninitialized), a region of RAM with a fixed layout determined at link time, not at runtime.
|
||||
|
||||
```
|
||||
Memory regions for our two variables:
|
||||
+------------------------------------------+
|
||||
| FLASH (read-only, 0x10000000+) |
|
||||
| - Code (instructions) |
|
||||
| - Literal pool (our 3 words) |
|
||||
| - String literals ("regular_fav_num...")|
|
||||
+------------------------------------------+
|
||||
| RAM .data section (0x20000000+) |
|
||||
| - static_fav_num @ 0x200005a8 <- pool |
|
||||
+------------------------------------------+
|
||||
| STACK (grows down from 0x20082000) |
|
||||
| - regular_fav_num (if not optimized) |
|
||||
| frame-relative, no fixed address |
|
||||
+------------------------------------------+
|
||||
| HEAP (grows up, between stack and .bss) |
|
||||
| - malloc/free only, nothing here today |
|
||||
+------------------------------------------+
|
||||
```
|
||||
|
||||
The pool ends at `0x1000029b`. At `0x1000029d` a new function begins, specifically `gpio_set_function`. The first two instructions, `push {r4}` (save caller's `r4` to the stack) and `mov.w r4, #256` (load a working constant), are a standard SDK function prologue, nothing to do with `main`. The `ldr r3, [pc, #48]`i r/. at `0x100002a3` (`gpio_set_function+6`) is that next function loading from **its own** literal pool further ahead in flash — proof that every function manages its own pool.
|
||||
|
||||
### Step 10: Examine Register Values
|
||||
|
||||
After stepping to `0x10000262` or later, check the registers:
|
||||
After breaking at `0x10000264`, check the registers:
|
||||
|
||||
```gdb
|
||||
(gdb) i r
|
||||
```
|
||||
|
||||
Pay attention to:
|
||||
- `r4` - Should hold `0x200005a8` (static variable's RAM address, loaded from literal pool)
|
||||
- `r1` - Used for `printf` arguments (holds `42` or the static variable value)
|
||||
- `r3` - Used for load/increment/store of the static variable
|
||||
- `pc` - Program counter (current instruction address)
|
||||
What you will actually see:
|
||||
|
||||
- `r4` = `0x200005a8` — the static variable's fixed RAM address. This was loaded from the literal pool in the function prologue and never changes across loop iterations.
|
||||
- `r1` = leftover value from the previous `printf` call (e.g. `0x40039044`). The breakpoint is stopped **at** `movs r1, #42` — that instruction has not executed yet, so `r1` does not yet hold `42`.
|
||||
- `r3` = leftover from prior operations (e.g. `0x10`). It will be used later in the loop body to load, increment, and store `static_fav_num`, but not yet.
|
||||
- `pc` = `0x10000264` — the loop top, pointing at the `movs r1, #42` instruction.
|
||||
|
||||
You can confirm `r4` holds the right address and value:
|
||||
|
||||
```gdb
|
||||
(gdb) x/1db $r4
|
||||
0x200005a8 <striped_spin_lock_num>: 42
|
||||
```
|
||||
|
||||
The `<striped_spin_lock_num>` label is just the nearest named global symbol in the SDK that GDB finds at that address — the actual variable stored there is our `static_fav_num`.
|
||||
|
||||
### Step 11: Watch the Static Variable Change
|
||||
|
||||
@@ -579,7 +799,7 @@ Now that we know the static variable lives at `0x200005a8`, examine it directly:
|
||||
|
||||
```gdb
|
||||
(gdb) x/1db 0x200005a8
|
||||
0x200005a8: 42
|
||||
0x200005a8 <striped_spin_lock_num>: 42
|
||||
```
|
||||
|
||||
Step through a full loop iteration (back to `0x10000264`) and re-examine:
|
||||
@@ -587,7 +807,7 @@ Step through a full loop iteration (back to `0x10000264`) and re-examine:
|
||||
```gdb
|
||||
(gdb) c
|
||||
(gdb) x/1db 0x200005a8
|
||||
0x200005a8: 43
|
||||
0x200005a8 <striped_spin_lock_num>: 43
|
||||
```
|
||||
|
||||
The value incremented from 42 to 43! Each loop iteration, the `adds r3, #1` at `0x1000027c` bumps it by 1, and `strb r3, [r4, #0]` at `0x1000027e` writes it back to RAM.
|
||||
@@ -598,12 +818,14 @@ Read the GPIO input register to see the button state:
|
||||
|
||||
```gdb
|
||||
(gdb) x/1wx 0xd0000004
|
||||
0xd0000004: 0x00008003
|
||||
```
|
||||
|
||||
The SIO GPIO input register at `0xd0000004` shows the current state of all GPIO pins. Bit 15 corresponds to our button on GPIO 15. To extract just bit 15:
|
||||
|
||||
```gdb
|
||||
(gdb) p/x (*(unsigned int *)0xd0000004 >> 15) & 1
|
||||
$1 = 0x1
|
||||
```
|
||||
|
||||
- Returns `1` when button is **not pressed** (pull-up holds it HIGH)
|
||||
@@ -613,7 +835,7 @@ TRY IT!
|
||||
|
||||
---
|
||||
|
||||
## 🔬 Part 7: Understanding the Assembly
|
||||
## Part 7: Understanding the Assembly
|
||||
|
||||
Now that we've explored the binary in GDB, let's make sense of the key patterns.
|
||||
|
||||
@@ -623,17 +845,22 @@ In GDB, examine the code at the start of the loop:
|
||||
|
||||
```gdb
|
||||
(gdb) x/5i 0x10000262
|
||||
0x10000262 <main+46>: ldr r4, [pc, #44] @ (0x10000290 <main+92>)
|
||||
=> 0x10000264 <main+48>: movs r1, #42 @ 0x2a
|
||||
0x10000266 <main+50>: ldr r0, [pc, #44] @ (0x10000294 <main+96>)
|
||||
0x10000268 <main+52>: bl 0x100031a4 <__wrap_printf>
|
||||
0x1000026c <main+56>: ldrb r1, [r4, #0]
|
||||
```
|
||||
|
||||
Look for this instruction:
|
||||
|
||||
```
|
||||
0x10000264: movs r1, #42 @ 0x2a
|
||||
0x10000264 <main+48>: movs r1, #42 @ 0x2a
|
||||
```
|
||||
|
||||
This loads the value `0x2a` (42 in decimal) directly into register `r1` for the first `printf` call.
|
||||
|
||||
**Key insight:** The compiler **optimized away** the `regular_fav_num` variable entirely! Since it's always 42 when printed, the compiler just uses the constant `42` directly. The `regular_fav_num++` after the print is also removed because it has no observable effect.
|
||||
**Key insight:** The compiler **never allocated stack space** for `regular_fav_num`. Since it is always `42` when printed, the compiler bakes the constant directly into the `movs r1, #42` instruction. The `regular_fav_num++` after the print is also removed because it has no observable effect — the variable is recreated as `42` on the next loop iteration anyway.
|
||||
|
||||
### Step 14: Analyze the Static Variable
|
||||
|
||||
@@ -641,11 +868,6 @@ Examine the static variable operations in the second half of the loop body:
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000274
|
||||
```
|
||||
|
||||
Look for the load-increment-store pattern using `r4` (which holds the static variable's RAM address):
|
||||
|
||||
```
|
||||
0x10000274 <main+64>: mov.w r1, #3489660928 @ 0xd0000000
|
||||
0x10000278 <main+68>: ldrb r3, [r4, #0]
|
||||
0x1000027a <main+70>: movs r2, #16
|
||||
@@ -658,14 +880,26 @@ Look for the load-increment-store pattern using `r4` (which holds the static var
|
||||
0x1000028e <main+90>: b.n 0x10000264 <main+48>
|
||||
```
|
||||
|
||||
Look for the load-increment-store pattern using `r4` (which holds the static variable's RAM address):
|
||||
|
||||
```
|
||||
...
|
||||
0x10000278 <main+68>: ldrb r3, [r4, #0]
|
||||
0x1000027a <main+70>: movs r2, #16
|
||||
0x1000027c <main+72>: adds r3, #1
|
||||
0x1000027e <main+74>: strb r3, [r4, #0]
|
||||
...
|
||||
```
|
||||
|
||||
Note that `r4` was loaded earlier at `0x10000262` via `ldr r4, [pc, #44]` - this pulled the static variable's RAM address (`0x200005a8`) from the literal pool at `0x10000290`.
|
||||
|
||||
**Key insight:** The static variable lives at a **fixed RAM address** (`0x200005a8`). It's loaded, incremented, and stored back - unlike the regular variable which was optimized away!
|
||||
**Key insight:** The static variable lives at a **fixed RAM address** (`0x200005a8`). It's loaded, incremented, and stored back. The regular variable, by contrast, never gets a stack slot — the compiler holds it in a register and bakes the constant `42` directly into the instruction, so there is nothing to load or store.
|
||||
|
||||
Verify the static variable value which should be `43`:
|
||||
|
||||
```gdb
|
||||
(gdb) x/1db 0x200005a8
|
||||
0x200005a8 <striped_spin_lock_num>: 43
|
||||
```
|
||||
|
||||
### Step 15: Analyze the GPIO Logic
|
||||
@@ -674,11 +908,6 @@ Examine the GPIO input/output code:
|
||||
|
||||
```gdb
|
||||
(gdb) x/10i 0x10000274
|
||||
```
|
||||
|
||||
Look for this sequence:
|
||||
|
||||
```
|
||||
0x10000274 <main+64>: mov.w r1, #3489660928 @ 0xd0000000
|
||||
0x10000278 <main+68>: ldrb r3, [r4, #0]
|
||||
0x1000027a <main+70>: movs r2, #16
|
||||
@@ -713,14 +942,14 @@ Look for this sequence:
|
||||
The last instruction at `0x1000028e` is already covered in the table above:
|
||||
|
||||
```
|
||||
0x1000028e: b.n 0x10000264
|
||||
0x1000028e <main+90>: b.n 0x10000264 <main+48>
|
||||
```
|
||||
|
||||
This is an **unconditional branch** back to `0x10000264` (the `movs r1, #42` at the top of the loop) - this is the `while (true)` in our code! There is no `pop` or `bx lr` to return from `main` because the loop never exits.
|
||||
|
||||
---
|
||||
|
||||
## ✏️ Part 8: Hacking the Binary with a Hex Editor
|
||||
## Part 8: Hacking the Binary with a Hex Editor
|
||||
|
||||
Now for the fun part - we'll patch the `.bin` file directly using a hex editor!
|
||||
|
||||
@@ -779,11 +1008,11 @@ This is the 32-bit Thumb-2 encoding of `eor.w r3, r3, #1`. The bytes break down
|
||||
|
||||
```
|
||||
+-----------------------------------------------------------------+
|
||||
| eor.w r3, r3, #1 -> bytes: 83 F0 01 03 |
|
||||
| eor.w r3, r3, #1 -> bytes: 83 F0 01 03 |
|
||||
| |
|
||||
| Byte 0: 0x83 -?? |
|
||||
| Byte 0: 0x83 -?? |
|
||||
| Byte 1: 0xF0 -+ First halfword (opcode + source register) |
|
||||
| Byte 2: 0x01 ---- Immediate value (#1) ?? CHANGE THIS |
|
||||
| Byte 2: 0x01 ---- Immediate value (#1) ?? CHANGE THIS |
|
||||
| Byte 3: 0x03 ---- Destination register (r3) |
|
||||
| |
|
||||
+-----------------------------------------------------------------+
|
||||
@@ -816,19 +1045,19 @@ This is the **opposite** of the original behavior!
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Part 9: Converting and Flashing the Hacked Binary
|
||||
## Part 9: Converting and Flashing the Hacked Binary
|
||||
|
||||
### Step 22: Convert to UF2 Format
|
||||
|
||||
Open a terminal and navigate to your project directory:
|
||||
|
||||
```powershell
|
||||
```cmd
|
||||
cd C:\Users\flare-vm\Desktop\Embedded-Hacking-main\0x0014_static-variables
|
||||
```
|
||||
|
||||
Run the conversion command:
|
||||
|
||||
```powershell
|
||||
```cmd
|
||||
python ..\uf2conv.py build\0x0014_static-variables-h.bin --base 0x10000000 --family 0xe48bff59 --output build\hacked.uf2
|
||||
```
|
||||
|
||||
@@ -859,13 +1088,13 @@ static_fav_num: 43
|
||||
- LED should now be **ON by default** (when button is NOT pressed)
|
||||
- LED should turn **OFF** when you press the button
|
||||
|
||||
🎉 **BOOM! We successfully:**
|
||||
**BOOM! We successfully:**
|
||||
1. Changed the printed value from 42 to 43
|
||||
2. Inverted the LED/button logic
|
||||
|
||||
---
|
||||
|
||||
## 📊 Part 10: Summary and Review
|
||||
## Part 10: Summary and Review
|
||||
|
||||
### What We Accomplished
|
||||
|
||||
@@ -945,7 +1174,7 @@ static_fav_num: 43
|
||||
|
||||
---
|
||||
|
||||
## 💡 Key Takeaways
|
||||
## Key Takeaways
|
||||
|
||||
1. **Static variables persist** - They keep their value between function calls and loop iterations.
|
||||
|
||||
@@ -969,7 +1198,7 @@ static_fav_num: 43
|
||||
|
||||
---
|
||||
|
||||
## 📖 Glossary
|
||||
## Glossary
|
||||
|
||||
| Term | Definition |
|
||||
| --------------------- | ---------------------------------------------------------------- |
|
||||
@@ -992,7 +1221,7 @@ static_fav_num: 43
|
||||
|
||||
---
|
||||
|
||||
## 📚 Additional Resources
|
||||
## Additional Resources
|
||||
|
||||
### GPIO Input Reference
|
||||
|
||||
@@ -1037,3 +1266,4 @@ static_fav_num: 43
|
||||
Happy hacking! ?
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Background grid decoration -->
|
||||
<g opacity="0.06">
|
||||
<line x1="0" y1="100" x2="1200" y2="100" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="200" x2="1200" y2="200" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="300" x2="1200" y2="300" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="400" x2="1200" y2="400" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="500" x2="1200" y2="500" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="600" x2="1200" y2="600" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="0" y1="700" x2="1200" y2="700" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="200" y1="0" x2="200" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="400" y1="0" x2="400" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="600" y1="0" x2="600" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="800" y1="0" x2="800" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
<line x1="1000" y1="0" x2="1000" y2="800" stroke="#00ff41" stroke-width="1"/>
|
||||
</g>
|
||||
|
||||
<!-- Hex rain decoration -->
|
||||
<g opacity="0.04" font-family="'Courier New',monospace" font-size="14" fill="#00ff41">
|
||||
<text x="50" y="80">4F 70 65 6E 4F 43 44</text>
|
||||
<text x="900" y="120">10 00 02 34 08 B5 01</text>
|
||||
<text x="150" y="180">47 44 42 20 52 45 56</text>
|
||||
<text x="800" y="240">20 08 20 00 FF AA 00</text>
|
||||
<text x="80" y="350">52 50 32 33 35 30 00</text>
|
||||
<text x="950" y="380">0A 0A 0F 12 12 1A 1A</text>
|
||||
<text x="100" y="520">41 52 4D 76 38 2D 4D</text>
|
||||
<text x="870" y="560">00 FF 41 00 D4 FF 88</text>
|
||||
<text x="60" y="680">47 48 49 44 52 41 00</text>
|
||||
<text x="920" y="720">FF 00 40 C0 C0 C0 00</text>
|
||||
</g>
|
||||
|
||||
<!-- Corner accents -->
|
||||
<polyline points="30,30 30,80 80,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="1170,30 1170,80 1120,80" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="30,770 30,720 80,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
<polyline points="1170,770 1170,720 1120,720" fill="none" stroke="#00ff41" stroke-width="2" opacity="0.3"/>
|
||||
|
||||
<!-- Top accent line -->
|
||||
<rect x="100" y="140" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
|
||||
|
||||
<!-- Course Title -->
|
||||
<text x="600" y="210" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Embedded Systems</text>
|
||||
<text x="600" y="278" text-anchor="middle" font-family="'Courier New',monospace" font-size="56" font-weight="bold" fill="#00ff41">Reverse Engineering</text>
|
||||
|
||||
<!-- Divider -->
|
||||
<rect x="300" y="310" width="600" height="2" fill="#00d4ff" opacity="0.6"/>
|
||||
|
||||
<!-- Week Number -->
|
||||
<text x="600" y="380" text-anchor="middle" font-family="'Courier New',monospace" font-size="42" font-weight="bold" fill="#00d4ff">// WEEK 06</text>
|
||||
|
||||
<!-- Week Topic -->
|
||||
<text x="600" y="440" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Static Variables in Embedded Systems:</text>
|
||||
<text x="600" y="478" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">Debugging and Hacking Static Variables</text>
|
||||
<text x="600" y="516" text-anchor="middle" font-family="'Courier New',monospace" font-size="28" fill="#c0c0c0">w/ GPIO Input Basics</text>
|
||||
|
||||
<!-- Bottom accent line -->
|
||||
<rect x="100" y="570" width="1000" height="2" fill="#00ff41" opacity="0.4"/>
|
||||
|
||||
<!-- University -->
|
||||
<text x="600" y="635" text-anchor="middle" font-family="'Courier New',monospace" font-size="36" font-weight="bold" fill="#ffaa00">George Mason University</text>
|
||||
|
||||
<!-- Bottom badge -->
|
||||
<rect x="400" y="670" width="400" height="40" rx="20" fill="none" stroke="#00ff41" stroke-width="1.5" opacity="0.5"/>
|
||||
<text x="600" y="697" text-anchor="middle" font-family="'Courier New',monospace" font-size="20" fill="#00ff41" opacity="0.7">RP2350 // ARM Cortex-M33</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,74 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Static vs Regular Vars</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Persistence across loop iterations</text>
|
||||
|
||||
<!-- Regular Variable -->
|
||||
<rect x="40" y="110" width="540" height="310" rx="8" class="pnl"/>
|
||||
<text x="310" y="148" text-anchor="middle" class="sub">Regular (auto)</text>
|
||||
|
||||
<rect x="60" y="168" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="202" class="red">Loop 1: 42 -> 43 -> destroy</text>
|
||||
|
||||
<rect x="60" y="233" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="267" class="red">Loop 2: 42 -> 43 -> destroy</text>
|
||||
|
||||
<rect x="60" y="298" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="332" class="red">Loop 3: 42 -> 43 -> destroy</text>
|
||||
|
||||
<text x="60" y="393" class="txt">Always prints:</text>
|
||||
<text x="340" y="393" class="red">42</text>
|
||||
|
||||
<!-- Static Variable -->
|
||||
<rect x="620" y="110" width="540" height="310" rx="8" class="pnl"/>
|
||||
<text x="890" y="148" text-anchor="middle" class="sub">Static</text>
|
||||
|
||||
<rect x="640" y="168" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="202" class="grn">Loop 1: 42 -> 43 (kept!)</text>
|
||||
|
||||
<rect x="640" y="233" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="267" class="grn">Loop 2: 43 -> 44 (kept!)</text>
|
||||
|
||||
<rect x="640" y="298" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="660" y="332" class="grn">Loop 3: 44 -> 45 (kept!)</text>
|
||||
|
||||
<text x="640" y="393" class="txt">Keeps incrementing:</text>
|
||||
<text x="960" y="393" class="grn">42,43,44...</text>
|
||||
|
||||
<!-- Code Example -->
|
||||
<rect x="40" y="440" width="1120" height="160" rx="8" class="pnl"/>
|
||||
<text x="600" y="478" text-anchor="middle" class="sub">Declaration Syntax</text>
|
||||
|
||||
<rect x="60" y="498" width="500" height="80" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="530" class="txt">uint8_t reg = 42;</text>
|
||||
<text x="80" y="558" class="dim">Recreated each iteration</text>
|
||||
|
||||
<rect x="620" y="498" width="520" height="80" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="640" y="530" class="grn">static uint8_t s = 42;</text>
|
||||
<text x="640" y="558" class="dim">Persists for program life</text>
|
||||
|
||||
<!-- Overflow Note -->
|
||||
<rect x="40" y="620" width="1120" height="160" rx="8" class="pnl"/>
|
||||
<text x="600" y="658" text-anchor="middle" class="sub">uint8_t Overflow</text>
|
||||
|
||||
<text x="60" y="698" class="txt">255 + 1 =</text>
|
||||
<text x="260" y="698" class="red">0</text>
|
||||
<text x="320" y="698" class="dim">(wraps around!)</text>
|
||||
|
||||
<text x="60" y="733" class="dim">Binary: 11111111 + 1 = 100000000 (9 bits)</text>
|
||||
<text x="60" y="763" class="dim">Only 8 bits kept: 00000000 = 0</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Memory Layout</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Where variables live in RAM</text>
|
||||
|
||||
<!-- Memory Diagram -->
|
||||
<rect x="40" y="110" width="540" height="670" rx="8" class="pnl"/>
|
||||
<text x="310" y="148" text-anchor="middle" class="sub">RP2350 SRAM Map</text>
|
||||
|
||||
<!-- Stack -->
|
||||
<rect x="60" y="170" width="380" height="90" rx="4" fill="#ff0040" stroke="#ff0040" stroke-width="1" opacity="0.15"/>
|
||||
<text x="250" y="205" text-anchor="middle" class="red">STACK (grows down)</text>
|
||||
<text x="250" y="235" text-anchor="middle" class="dim">Local/auto variables</text>
|
||||
|
||||
<text x="455" y="210" class="dim">0x20082000</text>
|
||||
|
||||
<!-- Free Space -->
|
||||
<rect x="60" y="270" width="380" height="100" rx="4" fill="#1a1a2e" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="250" y="325" text-anchor="middle" class="dim">(free space)</text>
|
||||
|
||||
<!-- Heap -->
|
||||
<rect x="60" y="380" width="380" height="90" rx="4" fill="#ffaa00" stroke="#ffaa00" stroke-width="1" opacity="0.15"/>
|
||||
<text x="250" y="415" text-anchor="middle" class="amb">HEAP (grows up)</text>
|
||||
<text x="250" y="445" text-anchor="middle" class="dim">malloc / free</text>
|
||||
|
||||
<!-- .bss -->
|
||||
<rect x="60" y="480" width="380" height="90" rx="4" fill="#00d4ff" stroke="#00d4ff" stroke-width="1" opacity="0.15"/>
|
||||
<text x="250" y="515" text-anchor="middle" class="cyn">.bss section</text>
|
||||
<text x="250" y="545" text-anchor="middle" class="dim">Uninit static/global</text>
|
||||
|
||||
<!-- .data -->
|
||||
<rect x="60" y="580" width="380" height="90" rx="4" fill="#00ff41" stroke="#00ff41" stroke-width="1" opacity="0.15"/>
|
||||
<text x="250" y="615" text-anchor="middle" class="grn">.data section</text>
|
||||
<text x="250" y="645" text-anchor="middle" class="dim">Initialized static/global</text>
|
||||
|
||||
<text x="455" y="650" class="dim">0x20000000</text>
|
||||
|
||||
<text x="60" y="730" class="dim">Static vars: .data (init)</text>
|
||||
<text x="60" y="755" class="dim">Static vars: .bss (uninit)</text>
|
||||
|
||||
<!-- Variable Types Table -->
|
||||
<rect x="620" y="110" width="540" height="390" rx="8" class="pnl"/>
|
||||
<text x="890" y="148" text-anchor="middle" class="sub">Variable Storage</text>
|
||||
|
||||
<text x="640" y="188" class="cyn">Type</text>
|
||||
<text x="880" y="188" class="cyn">Location</text>
|
||||
|
||||
<line x1="640" y1="198" x2="1140" y2="198" stroke="#1a1a2e" stroke-width="1"/>
|
||||
|
||||
<text x="640" y="228" class="txt">Automatic</text>
|
||||
<text x="880" y="228" class="red">Stack</text>
|
||||
|
||||
<text x="640" y="258" class="txt">Static</text>
|
||||
<text x="880" y="258" class="grn">.data / .bss</text>
|
||||
|
||||
<text x="640" y="288" class="txt">Global</text>
|
||||
<text x="880" y="288" class="grn">.data / .bss</text>
|
||||
|
||||
<text x="640" y="318" class="txt">Dynamic</text>
|
||||
<text x="880" y="318" class="amb">Heap</text>
|
||||
|
||||
<text x="640" y="358" class="dim">Static vars are NOT on heap!</text>
|
||||
<text x="640" y="383" class="dim">Fixed location, set at compile</text>
|
||||
<text x="640" y="408" class="dim">time. Lives entire program.</text>
|
||||
<text x="640" y="448" class="grn">Example:</text>
|
||||
<text x="640" y="473" class="dim">static_fav_num @ 0x200005A8</text>
|
||||
|
||||
<!-- Key Insight -->
|
||||
<rect x="620" y="520" width="540" height="260" rx="8" class="pnl"/>
|
||||
<text x="890" y="548" text-anchor="middle" class="sub">Key Insight</text>
|
||||
|
||||
<text x="640" y="588" class="txt">Stack vars:</text>
|
||||
<text x="640" y="618" class="red">Created + destroyed</text>
|
||||
<text x="640" y="648" class="dim">each function call</text>
|
||||
|
||||
<text x="640" y="693" class="txt">Static vars:</text>
|
||||
<text x="640" y="723" class="grn">Fixed RAM address</text>
|
||||
<text x="640" y="753" class="dim">persist entire runtime</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,93 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">GPIO Input Basics</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Reading buttons with the RP2350</text>
|
||||
|
||||
<!-- Output vs Input -->
|
||||
<rect x="40" y="110" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="310" y="148" text-anchor="middle" class="sub">OUTPUT (before)</text>
|
||||
|
||||
<rect x="60" y="170" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="80" y="204" class="grn">Pico GPIO 16</text>
|
||||
<text x="370" y="204" class="txt">--></text>
|
||||
<text x="420" y="204" class="amb">LED</text>
|
||||
|
||||
<text x="60" y="268" class="dim">We CONTROL the LED</text>
|
||||
<text x="60" y="293" class="dim">gpio_put(pin, value)</text>
|
||||
|
||||
<rect x="620" y="110" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="890" y="148" text-anchor="middle" class="sub">INPUT (new!)</text>
|
||||
|
||||
<rect x="640" y="170" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="660" y="204" class="cyn">Pico GPIO 15</text>
|
||||
<text x="950" y="204" class="txt"><--</text>
|
||||
<text x="1000" y="204" class="amb">BTN</text>
|
||||
|
||||
<text x="640" y="268" class="dim">We READ button state</text>
|
||||
<text x="640" y="293" class="dim">gpio_get(pin)</text>
|
||||
|
||||
<!-- Floating Input Problem -->
|
||||
<rect x="40" y="330" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="310" y="368" text-anchor="middle" class="sub">Floating Input</text>
|
||||
|
||||
<text x="60" y="408" class="txt">No connection =</text>
|
||||
<text x="60" y="438" class="red">RANDOM values!</text>
|
||||
|
||||
<text x="60" y="478" class="dim">Read 1: HIGH</text>
|
||||
<text x="260" y="478" class="dim">Read 2: LOW</text>
|
||||
<text x="60" y="503" class="dim">Read 3: HIGH</text>
|
||||
<text x="260" y="503" class="dim">Read 4: HIGH</text>
|
||||
<text x="440" y="503" class="dim">???</text>
|
||||
|
||||
<!-- Pull Resistors -->
|
||||
<rect x="620" y="330" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="890" y="368" text-anchor="middle" class="sub">Pull Resistors</text>
|
||||
|
||||
<text x="640" y="408" class="cyn">Type</text>
|
||||
<text x="840" y="408" class="cyn">Default</text>
|
||||
<text x="1000" y="408" class="cyn">Pressed</text>
|
||||
|
||||
<line x1="640" y1="418" x2="1140" y2="418" stroke="#1a1a2e" stroke-width="1"/>
|
||||
|
||||
<text x="640" y="448" class="amb">Pull-Up</text>
|
||||
<text x="840" y="448" class="grn">HIGH(1)</text>
|
||||
<text x="1000" y="448" class="red">LOW(0)</text>
|
||||
|
||||
<text x="640" y="483" class="amb">Pull-Down</text>
|
||||
<text x="840" y="483" class="red">LOW(0)</text>
|
||||
<text x="1000" y="483" class="grn">HIGH(1)</text>
|
||||
|
||||
<text x="640" y="513" class="dim">Pico 2 has internal pull resistors!</text>
|
||||
|
||||
<!-- GPIO Functions -->
|
||||
<rect x="40" y="550" width="1120" height="230" rx="8" class="pnl"/>
|
||||
<text x="600" y="588" text-anchor="middle" class="sub">GPIO Input Functions</text>
|
||||
|
||||
<text x="60" y="628" class="grn">gpio_init(pin)</text>
|
||||
<text x="500" y="628" class="dim">Initialize pin</text>
|
||||
|
||||
<text x="60" y="658" class="grn">gpio_set_dir(pin, GPIO_IN)</text>
|
||||
<text x="500" y="658" class="dim">Set as input</text>
|
||||
|
||||
<text x="60" y="688" class="grn">gpio_pull_up(pin)</text>
|
||||
<text x="500" y="688" class="dim">Enable pull-up</text>
|
||||
|
||||
<text x="60" y="718" class="grn">gpio_get(pin)</text>
|
||||
<text x="500" y="718" class="dim">Read state (0 or 1)</text>
|
||||
|
||||
<text x="60" y="748" class="dim">No external resistor needed -- internal pull-up!</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,99 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Pull-Up Resistor</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Internal pull-up on GPIO 15</text>
|
||||
|
||||
<!-- Circuit Diagram -->
|
||||
<rect x="40" y="110" width="540" height="370" rx="8" class="pnl"/>
|
||||
<text x="310" y="148" text-anchor="middle" class="sub">Circuit</text>
|
||||
|
||||
<text x="160" y="195" class="amb">3.3V</text>
|
||||
<line x1="195" y1="205" x2="195" y2="240" stroke="#ffaa00" stroke-width="2"/>
|
||||
|
||||
<rect x="175" y="240" width="40" height="60" rx="2" fill="none" stroke="#ffaa00" stroke-width="2"/>
|
||||
<text x="240" y="275" class="dim">pull-up R</text>
|
||||
|
||||
<line x1="195" y1="300" x2="195" y2="340" stroke="#ffaa00" stroke-width="2"/>
|
||||
<line x1="195" y1="340" x2="350" y2="340" stroke="#00d4ff" stroke-width="2"/>
|
||||
<text x="370" y="345" class="cyn">GPIO 15</text>
|
||||
|
||||
<line x1="195" y1="340" x2="195" y2="380" stroke="#888" stroke-width="2"/>
|
||||
|
||||
<rect x="170" y="380" width="50" height="30" rx="2" fill="none" stroke="#c0c0c0" stroke-width="2"/>
|
||||
<text x="240" y="400" class="dim">BTN</text>
|
||||
|
||||
<line x1="195" y1="410" x2="195" y2="450" stroke="#888" stroke-width="2"/>
|
||||
<text x="160" y="465" class="dim">GND</text>
|
||||
|
||||
<!-- Logic Table -->
|
||||
<rect x="620" y="110" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="890" y="148" text-anchor="middle" class="sub">Button Logic</text>
|
||||
|
||||
<text x="640" y="188" class="cyn">State</text>
|
||||
<text x="840" y="188" class="cyn">GPIO</text>
|
||||
<text x="1000" y="188" class="cyn">LED</text>
|
||||
|
||||
<line x1="640" y1="198" x2="1140" y2="198" stroke="#1a1a2e" stroke-width="1"/>
|
||||
|
||||
<text x="640" y="233" class="txt">Released</text>
|
||||
<text x="840" y="233" class="grn">HIGH (1)</text>
|
||||
<text x="1000" y="233" class="red">OFF</text>
|
||||
|
||||
<text x="640" y="268" class="txt">Pressed</text>
|
||||
<text x="840" y="268" class="red">LOW (0)</text>
|
||||
<text x="1000" y="268" class="grn">ON</text>
|
||||
|
||||
<text x="640" y="293" class="dim">Inverted! Pull-up = backwards</text>
|
||||
|
||||
<!-- Ternary Operator -->
|
||||
<rect x="620" y="330" width="540" height="150" rx="8" class="pnl"/>
|
||||
<text x="890" y="368" text-anchor="middle" class="sub">Ternary Operator</text>
|
||||
|
||||
<rect x="640" y="390" width="500" height="40" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="660" y="418" class="amb">gpio_put(LED, pressed?0:1);</text>
|
||||
|
||||
<text x="640" y="460" class="dim">pressed=1 -> LED OFF (inverted!)</text>
|
||||
|
||||
<!-- Wiring -->
|
||||
<rect x="40" y="500" width="1120" height="280" rx="8" class="pnl"/>
|
||||
<text x="600" y="538" text-anchor="middle" class="sub">Hardware Wiring</text>
|
||||
|
||||
<rect x="60" y="560" width="300" height="190" rx="6" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="210" y="590" text-anchor="middle" class="cyn">Pico 2</text>
|
||||
<text x="80" y="625" class="grn">GPIO 15</text>
|
||||
<text x="80" y="660" class="amb">GPIO 16</text>
|
||||
<text x="80" y="695" class="dim">GND</text>
|
||||
<text x="80" y="725" class="dim">BOOTSEL</text>
|
||||
|
||||
<text x="380" y="625" class="txt">--></text>
|
||||
<text x="380" y="660" class="txt">--></text>
|
||||
<text x="380" y="695" class="txt">--></text>
|
||||
|
||||
<rect x="440" y="560" width="300" height="190" rx="6" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="590" y="590" text-anchor="middle" class="amb">Components</text>
|
||||
<text x="460" y="625" class="txt">Button (one leg)</text>
|
||||
<text x="460" y="660" class="txt">LED + resistor</text>
|
||||
<text x="460" y="695" class="txt">Button (other leg)</text>
|
||||
<text x="460" y="725" class="dim">Hold to flash UF2</text>
|
||||
|
||||
<rect x="780" y="560" width="360" height="190" rx="6" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="960" y="590" text-anchor="middle" class="grn">Key Point</text>
|
||||
<text x="800" y="625" class="txt">No external</text>
|
||||
<text x="800" y="655" class="txt">resistor needed!</text>
|
||||
<text x="800" y="695" class="dim">Internal pull-up</text>
|
||||
<text x="800" y="720" class="dim">handles it all</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,83 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Source Code</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">0x0014_static-variables.c</text>
|
||||
|
||||
<!-- Code Panel -->
|
||||
<rect x="40" y="110" width="700" height="510" rx="8" class="pnl"/>
|
||||
<text x="390" y="148" text-anchor="middle" class="sub">main()</text>
|
||||
|
||||
<rect x="60" y="168" width="660" height="440" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="198" class="cyn">int main(void) {</text>
|
||||
<text x="110" y="226" class="txt">stdio_init_all();</text>
|
||||
<text x="110" y="254" class="dim">// GPIO setup</text>
|
||||
<text x="110" y="282" class="txt">gpio_init(15);</text>
|
||||
<text x="110" y="310" class="txt">gpio_set_dir(15, GPIO_IN);</text>
|
||||
<text x="110" y="338" class="amb">gpio_pull_up(15);</text>
|
||||
<text x="110" y="366" class="txt">gpio_init(16);</text>
|
||||
<text x="110" y="394" class="txt">gpio_set_dir(16, GPIO_OUT);</text>
|
||||
<text x="110" y="430" class="cyn">while (true) {</text>
|
||||
<text x="140" y="458" class="txt">uint8_t reg = 42;</text>
|
||||
<text x="140" y="486" class="grn">static uint8_t s = 42;</text>
|
||||
<text x="140" y="514" class="txt">printf(... reg, s);</text>
|
||||
<text x="140" y="542" class="red">reg++; s++;</text>
|
||||
<text x="110" y="570" class="cyn">}</text>
|
||||
<text x="80" y="590" class="cyn">}</text>
|
||||
|
||||
<!-- Annotations -->
|
||||
<rect x="780" y="110" width="380" height="180" rx="8" class="pnl"/>
|
||||
<text x="970" y="148" text-anchor="middle" class="sub">GPIO Setup</text>
|
||||
|
||||
<text x="800" y="183" class="grn">Pin 15:</text>
|
||||
<text x="920" y="183" class="txt">Input</text>
|
||||
<text x="800" y="213" class="dim">Pull-up enabled</text>
|
||||
|
||||
<text x="800" y="248" class="amb">Pin 16:</text>
|
||||
<text x="920" y="248" class="txt">Output</text>
|
||||
<text x="800" y="268" class="dim">LED control</text>
|
||||
|
||||
<!-- Serial Output -->
|
||||
<rect x="780" y="310" width="380" height="200" rx="8" class="pnl"/>
|
||||
<text x="970" y="348" text-anchor="middle" class="sub">Serial Output</text>
|
||||
|
||||
<rect x="800" y="370" width="340" height="115" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="820" y="397" class="txt">reg: 42</text>
|
||||
<text x="820" y="422" class="txt">s: 42</text>
|
||||
<text x="820" y="447" class="txt">reg: 42</text>
|
||||
<text x="820" y="472" class="grn">s: 43</text>
|
||||
|
||||
<text x="800" y="498" class="dim">reg always 42, s grows</text>
|
||||
|
||||
<!-- Button Logic -->
|
||||
<rect x="780" y="530" width="380" height="90" rx="8" class="pnl"/>
|
||||
<text x="970" y="565" text-anchor="middle" class="sub">Button Logic</text>
|
||||
|
||||
<text x="800" y="598" class="dim">pressed = gpio_get(15);</text>
|
||||
|
||||
<!-- Key -->
|
||||
<rect x="40" y="640" width="1120" height="140" rx="8" class="pnl"/>
|
||||
<text x="600" y="678" text-anchor="middle" class="sub">Key Behaviors</text>
|
||||
|
||||
<rect x="60" y="698" width="340" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="230" y="730" text-anchor="middle" class="red">reg: always 42</text>
|
||||
|
||||
<rect x="420" y="698" width="340" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="590" y="730" text-anchor="middle" class="grn">s: 42,43,44...</text>
|
||||
|
||||
<rect x="780" y="698" width="360" height="55" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="960" y="730" text-anchor="middle" class="amb">wraps at 255->0</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
@@ -0,0 +1,65 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Compiler Optimizations</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">What the compiler does to your code</text>
|
||||
|
||||
<!-- Optimization 1: Regular var removed -->
|
||||
<rect x="40" y="110" width="1120" height="220" rx="8" class="pnl"/>
|
||||
<text x="600" y="148" text-anchor="middle" class="sub">Optimization 1: Dead Code Removal</text>
|
||||
|
||||
<rect x="60" y="170" width="500" height="135" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="200" class="red">Your code:</text>
|
||||
<text x="80" y="230" class="txt">uint8_t reg = 42;</text>
|
||||
<text x="80" y="260" class="txt">reg++;</text>
|
||||
<text x="80" y="285" class="dim">// No lasting effect!</text>
|
||||
|
||||
<rect x="620" y="170" width="520" height="135" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="640" y="200" class="grn">Compiler output:</text>
|
||||
<text x="640" y="230" class="amb">movs r1, #42</text>
|
||||
<text x="640" y="260" class="dim">// reg++ is GONE</text>
|
||||
<text x="640" y="285" class="dim">// Uses constant 42 directly</text>
|
||||
|
||||
<!-- Optimization 2: Function Inlining -->
|
||||
<rect x="40" y="350" width="1120" height="200" rx="8" class="pnl"/>
|
||||
<text x="600" y="388" text-anchor="middle" class="sub">Optimization 2: Function Inlining</text>
|
||||
|
||||
<rect x="60" y="410" width="500" height="110" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="440" class="red">Your code:</text>
|
||||
<text x="80" y="470" class="txt">gpio_pull_up(15);</text>
|
||||
<text x="80" y="500" class="dim">// Simple wrapper func</text>
|
||||
|
||||
<rect x="620" y="410" width="520" height="110" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="640" y="440" class="grn">Compiler output:</text>
|
||||
<text x="640" y="470" class="amb">gpio_set_pulls(15,1,0);</text>
|
||||
<text x="640" y="500" class="dim">// Inlined to real func</text>
|
||||
|
||||
<!-- Optimization 3: Instruction Scheduling -->
|
||||
<rect x="40" y="570" width="1120" height="210" rx="8" class="pnl"/>
|
||||
<text x="600" y="608" text-anchor="middle" class="sub">Optimization 3: Scheduling</text>
|
||||
|
||||
<text x="60" y="648" class="txt">Compiler reorders instructions</text>
|
||||
<text x="60" y="678" class="txt">to avoid pipeline stalls:</text>
|
||||
|
||||
<rect x="60" y="698" width="340" height="55" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="230" y="732" text-anchor="middle" class="cyn">Load SIO base</text>
|
||||
|
||||
<rect x="420" y="698" width="340" height="55" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="590" y="732" text-anchor="middle" class="amb">Increment s</text>
|
||||
|
||||
<rect x="780" y="698" width="340" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="950" y="732" text-anchor="middle" class="grn">Read GPIO</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
@@ -0,0 +1,90 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Assembly Analysis</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Key instructions in main() loop</text>
|
||||
|
||||
<!-- Assembly Listing -->
|
||||
<rect x="40" y="110" width="700" height="490" rx="8" class="pnl"/>
|
||||
<text x="390" y="148" text-anchor="middle" class="sub">Loop Body (0x10000264)</text>
|
||||
|
||||
<rect x="60" y="168" width="660" height="410" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="196" class="cyn">movs r1, #0x2a</text>
|
||||
<text x="420" y="196" class="dim">; reg=42</text>
|
||||
<text x="80" y="226" class="txt">bl __wrap_printf</text>
|
||||
<text x="420" y="226" class="dim">; print reg</text>
|
||||
<text x="80" y="256" class="amb">ldrb r1, [r4]</text>
|
||||
<text x="420" y="256" class="dim">; load static</text>
|
||||
<text x="80" y="286" class="txt">bl __wrap_printf</text>
|
||||
<text x="420" y="286" class="dim">; print s</text>
|
||||
<text x="80" y="316" class="red">mov.w r1, #0xd0000000</text>
|
||||
<text x="420" y="316" class="dim">; SIO base</text>
|
||||
<text x="80" y="346" class="amb">ldrb r3, [r4]</text>
|
||||
<text x="420" y="346" class="dim">; reload s</text>
|
||||
<text x="80" y="376" class="grn">adds r3, #1</text>
|
||||
<text x="420" y="376" class="dim">; s++</text>
|
||||
<text x="80" y="406" class="grn">strb r3, [r4]</text>
|
||||
<text x="420" y="406" class="dim">; store s</text>
|
||||
<text x="80" y="436" class="cyn">ldr r3, [r1, #4]</text>
|
||||
<text x="420" y="436" class="dim">; read GPIO</text>
|
||||
<text x="80" y="466" class="cyn">ubfx r3, r3, #15, #1</text>
|
||||
<text x="420" y="466" class="dim">; bit 15</text>
|
||||
<text x="80" y="496" class="red">eor.w r3, r3, #1</text>
|
||||
<text x="420" y="496" class="dim">; invert</text>
|
||||
<text x="80" y="526" class="amb">mcrr 0, 4, r2, r3, cr0</text>
|
||||
<text x="420" y="526" class="dim">; GPIO out</text>
|
||||
<text x="80" y="556" class="cyn">b.n 0x10000264</text>
|
||||
<text x="420" y="556" class="dim">; loop</text>
|
||||
|
||||
<!-- Key Registers -->
|
||||
<rect x="780" y="110" width="380" height="220" rx="8" class="pnl"/>
|
||||
<text x="970" y="148" text-anchor="middle" class="sub">Key Registers</text>
|
||||
|
||||
<text x="800" y="188" class="cyn">r1:</text>
|
||||
<text x="860" y="188" class="txt">printf arg</text>
|
||||
<text x="800" y="223" class="amb">r3:</text>
|
||||
<text x="860" y="223" class="txt">temp / static</text>
|
||||
<text x="800" y="258" class="grn">r4:</text>
|
||||
<text x="860" y="258" class="txt">0x200005a8</text>
|
||||
<text x="800" y="283" class="dim">(static var addr)</text>
|
||||
<text x="800" y="308" class="red">r2:</text>
|
||||
<text x="860" y="308" class="txt">LED pin (16)</text>
|
||||
|
||||
<!-- Key Instructions -->
|
||||
<rect x="780" y="350" width="380" height="250" rx="8" class="pnl"/>
|
||||
<text x="970" y="388" text-anchor="middle" class="sub">Key Patterns</text>
|
||||
|
||||
<text x="800" y="428" class="grn">ldrb/adds/strb</text>
|
||||
<text x="800" y="453" class="dim">Load-increment-store</text>
|
||||
<text x="800" y="478" class="dim">(static var update)</text>
|
||||
|
||||
<text x="800" y="518" class="cyn">ubfx #15, #1</text>
|
||||
<text x="800" y="543" class="dim">Extract GPIO bit 15</text>
|
||||
|
||||
<text x="800" y="573" class="red">eor.w #1</text>
|
||||
<text x="800" y="598" class="dim">Inverts (? 0 : 1)</text>
|
||||
|
||||
<!-- Infinite Loop -->
|
||||
<rect x="40" y="620" width="1120" height="160" rx="8" class="pnl"/>
|
||||
<text x="600" y="658" text-anchor="middle" class="sub">Infinite Loop</text>
|
||||
|
||||
<rect x="60" y="680" width="400" height="70" rx="4" fill="#0a0a0f" stroke="#00d4ff" stroke-width="1"/>
|
||||
<text x="80" y="715" class="cyn">b.n 0x10000264</text>
|
||||
<text x="80" y="738" class="dim">; while(true)</text>
|
||||
|
||||
<text x="500" y="715" class="txt">No pop/bx lr</text>
|
||||
<text x="500" y="745" class="dim">main() never returns</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,75 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">GDB: Static Variable</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Finding static_fav_num in RAM</text>
|
||||
|
||||
<!-- Literal Pool -->
|
||||
<rect x="40" y="110" width="1120" height="200" rx="8" class="pnl"/>
|
||||
<text x="600" y="148" text-anchor="middle" class="sub">Literal Pool Lookup</text>
|
||||
|
||||
<rect x="60" y="170" width="700" height="48" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="200" class="cyn">ldr r4, [pc, #44]</text>
|
||||
<text x="400" y="200" class="dim">@ 0x10000290</text>
|
||||
|
||||
<text x="60" y="248" class="txt">Examine literal pool:</text>
|
||||
<rect x="60" y="258" width="700" height="30" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="282" class="grn">x/1wx 0x10000290 = 0x200005A8</text>
|
||||
|
||||
<text x="790" y="248" class="amb">r4 now holds the</text>
|
||||
<text x="790" y="278" class="amb">RAM address of</text>
|
||||
<text x="790" y="298" class="grn">static_fav_num!</text>
|
||||
|
||||
<!-- Examining the Variable -->
|
||||
<rect x="40" y="330" width="540" height="220" rx="8" class="pnl"/>
|
||||
<text x="310" y="368" text-anchor="middle" class="sub">Read Value</text>
|
||||
|
||||
<rect x="60" y="390" width="500" height="40" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="418" class="grn">x/1db 0x200005a8 = 42</text>
|
||||
|
||||
<text x="60" y="458" class="dim">After one loop iteration:</text>
|
||||
<rect x="60" y="468" width="500" height="40" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="496" class="amb">x/1db 0x200005a8 = 43</text>
|
||||
|
||||
<text x="60" y="536" class="dim">It incremented! Persists in RAM.</text>
|
||||
|
||||
<!-- Disasm Gotcha -->
|
||||
<rect x="620" y="330" width="540" height="220" rx="8" class="pnl"/>
|
||||
<text x="890" y="368" text-anchor="middle" class="sub">Disasm Gotcha</text>
|
||||
|
||||
<text x="640" y="408" class="txt">x/i 0x10000290 shows:</text>
|
||||
|
||||
<rect x="640" y="425" width="500" height="40" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="660" y="453" class="red">lsls r0, r5, #22</text>
|
||||
|
||||
<text x="640" y="493" class="dim">GDB decodes DATA as code!</text>
|
||||
<text x="640" y="518" class="dim">Bytes A8 05 00 20 = 0x200005A8</text>
|
||||
<text x="640" y="538" class="dim">Use x/wx not x/i for data</text>
|
||||
|
||||
<!-- GPIO Register -->
|
||||
<rect x="40" y="570" width="1120" height="210" rx="8" class="pnl"/>
|
||||
<text x="600" y="608" text-anchor="middle" class="sub">GPIO Input Register</text>
|
||||
|
||||
<text x="60" y="648" class="txt">Read button state in GDB:</text>
|
||||
|
||||
<rect x="60" y="668" width="700" height="40" rx="4" fill="#0a0a0f" stroke="#1a1a2e" stroke-width="1"/>
|
||||
<text x="80" y="696" class="grn">p/x (*(uint*)0xd0000004 >> 15) & 1</text>
|
||||
|
||||
<text x="60" y="738" class="cyn">Returns 1:</text>
|
||||
<text x="260" y="738" class="dim">not pressed (pull-up)</text>
|
||||
<text x="60" y="758" class="amb">Returns 0:</text>
|
||||
<text x="260" y="758" class="dim">button pressed</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1,63 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Hacking the Binary</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Two patches with a hex editor</text>
|
||||
|
||||
<!-- Offset Formula -->
|
||||
<rect x="40" y="110" width="1120" height="100" rx="8" class="pnl"/>
|
||||
<text x="600" y="148" text-anchor="middle" class="sub">File Offset Formula</text>
|
||||
<text x="60" y="188" class="grn">offset = address - 0x10000000</text>
|
||||
<text x="600" y="188" class="dim">Example: 0x10000264 -> 0x264</text>
|
||||
|
||||
<!-- Hack 1 -->
|
||||
<rect x="40" y="230" width="1120" height="240" rx="8" class="pnl"/>
|
||||
<text x="600" y="268" text-anchor="middle" class="sub">Hack 1: Change 42 to 43</text>
|
||||
|
||||
<text x="60" y="308" class="txt">Target: movs r1, #0x2a</text>
|
||||
<text x="60" y="338" class="dim">at address 0x10000264 (offset 0x264)</text>
|
||||
|
||||
<rect x="60" y="358" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="393" class="red">Before: 2A 21</text>
|
||||
<text x="310" y="393" class="dim">movs r1, #42</text>
|
||||
|
||||
<rect x="620" y="358" width="520" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="640" y="393" class="grn">After: 2B 21</text>
|
||||
<text x="880" y="393" class="dim">movs r1, #43</text>
|
||||
|
||||
<text x="60" y="443" class="dim">Thumb encoding: imm8 byte first, opcode 0x21 second</text>
|
||||
|
||||
<!-- Hack 2 -->
|
||||
<rect x="40" y="490" width="1120" height="290" rx="8" class="pnl"/>
|
||||
<text x="600" y="528" text-anchor="middle" class="sub">Hack 2: Invert Button Logic</text>
|
||||
|
||||
<text x="60" y="568" class="txt">Target: eor.w r3, r3, #1</text>
|
||||
<text x="60" y="598" class="dim">at address 0x10000286 (offset 0x286)</text>
|
||||
|
||||
<rect x="60" y="618" width="500" height="55" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="80" y="653" class="red">Before: 83 F0 01 03</text>
|
||||
|
||||
<rect x="620" y="618" width="520" height="55" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="640" y="653" class="grn">After: 83 F0 00 03</text>
|
||||
|
||||
<text x="60" y="703" class="dim">Byte at offset 0x288:</text>
|
||||
<text x="380" y="703" class="red">01</text>
|
||||
<text x="430" y="703" class="txt">-></text>
|
||||
<text x="470" y="703" class="grn">00</text>
|
||||
|
||||
<text x="60" y="738" class="txt">XOR with 0 = no invert</text>
|
||||
<text x="60" y="758" class="dim">LED now ON by default, OFF when pressed</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,112 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1200 800">
|
||||
<style>
|
||||
.bg{fill:#0a0a0f}.pnl{fill:#12121a;stroke:#1a1a2e}.hdr{fill:#12121a}
|
||||
.title{font:bold 42px 'Courier New',monospace;fill:#00ff41}
|
||||
.sub{font:bold 28px 'Courier New',monospace;fill:#00d4ff}
|
||||
.txt{font:24px 'Courier New',monospace;fill:#c0c0c0}
|
||||
.dim{font:20px 'Courier New',monospace;fill:#888}
|
||||
.grn{font:bold 24px 'Courier New',monospace;fill:#00ff41}
|
||||
.red{font:bold 24px 'Courier New',monospace;fill:#ff0040}
|
||||
.cyn{font:bold 24px 'Courier New',monospace;fill:#00d4ff}
|
||||
.amb{font:bold 24px 'Courier New',monospace;fill:#ffaa00}
|
||||
.badge{stroke:#00ff41;rx:14}
|
||||
</style>
|
||||
<rect class="bg" width="1200" height="800"/>
|
||||
|
||||
<!-- Title -->
|
||||
<text x="600" y="52" text-anchor="middle" class="title">Static Vars & GPIO Input</text>
|
||||
<text x="600" y="88" text-anchor="middle" class="dim">Static variables, GPIO input, hacking</text>
|
||||
|
||||
<!-- Static vs Auto Table -->
|
||||
<rect x="40" y="110" width="540" height="300" rx="8" class="pnl"/>
|
||||
<text x="310" y="148" text-anchor="middle" class="sub">Static vs Auto</text>
|
||||
|
||||
<text x="60" y="188" class="cyn">Aspect</text>
|
||||
<text x="260" y="188" class="red">Auto</text>
|
||||
<text x="420" y="188" class="grn">Static</text>
|
||||
|
||||
<line x1="60" y1="198" x2="560" y2="198" stroke="#1a1a2e" stroke-width="1"/>
|
||||
|
||||
<text x="60" y="228" class="txt">Where</text>
|
||||
<text x="260" y="228" class="red">Stack</text>
|
||||
<text x="420" y="228" class="grn">.data</text>
|
||||
|
||||
<text x="60" y="258" class="txt">Life</text>
|
||||
<text x="260" y="258" class="red">Scope</text>
|
||||
<text x="420" y="258" class="grn">Forever</text>
|
||||
|
||||
<text x="60" y="288" class="txt">Init</text>
|
||||
<text x="260" y="288" class="red">Every</text>
|
||||
<text x="420" y="288" class="grn">Once</text>
|
||||
|
||||
<text x="60" y="318" class="txt">Keeps?</text>
|
||||
<text x="260" y="318" class="red">No</text>
|
||||
<text x="420" y="318" class="grn">Yes</text>
|
||||
|
||||
<text x="60" y="348" class="txt">Optimized?</text>
|
||||
<text x="260" y="348" class="red">Often</text>
|
||||
<text x="420" y="348" class="grn">In RAM</text>
|
||||
|
||||
<text x="60" y="388" class="dim">Compiler may remove auto vars</text>
|
||||
|
||||
<!-- GPIO Input -->
|
||||
<rect x="620" y="110" width="540" height="300" rx="8" class="pnl"/>
|
||||
<text x="890" y="148" text-anchor="middle" class="sub">GPIO Input Setup</text>
|
||||
|
||||
<text x="640" y="188" class="grn">1.</text>
|
||||
<text x="680" y="188" class="txt">gpio_init(pin)</text>
|
||||
|
||||
<text x="640" y="223" class="grn">2.</text>
|
||||
<text x="680" y="223" class="txt">gpio_set_dir(pin, GPIO_IN)</text>
|
||||
|
||||
<text x="640" y="258" class="grn">3.</text>
|
||||
<text x="680" y="258" class="txt">gpio_pull_up(pin)</text>
|
||||
|
||||
<text x="640" y="293" class="grn">4.</text>
|
||||
<text x="680" y="293" class="txt">gpio_get(pin)</text>
|
||||
|
||||
<text x="640" y="338" class="dim">Pull-up: released=HIGH</text>
|
||||
<text x="640" y="363" class="dim">pressed=LOW (inverted!)</text>
|
||||
<text x="640" y="388" class="dim">Internal R, no hardware</text>
|
||||
|
||||
<!-- Key Assembly -->
|
||||
<rect x="40" y="430" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="310" y="468" text-anchor="middle" class="sub">Key Instructions</text>
|
||||
|
||||
<text x="60" y="508" class="amb">ubfx r3,r3,#15,#1</text>
|
||||
<text x="60" y="533" class="dim">Extract single GPIO bit</text>
|
||||
|
||||
<text x="60" y="568" class="red">eor.w r3,r3,#1</text>
|
||||
<text x="60" y="593" class="dim">XOR to invert logic</text>
|
||||
|
||||
<text x="60" y="618" class="cyn">b.n 0x10000264</text>
|
||||
|
||||
<!-- Hacking Workflow -->
|
||||
<rect x="620" y="430" width="540" height="200" rx="8" class="pnl"/>
|
||||
<text x="890" y="468" text-anchor="middle" class="sub">Hacking Workflow</text>
|
||||
|
||||
<text x="640" y="508" class="grn">1.</text>
|
||||
<text x="680" y="508" class="txt">Analyze in GDB</text>
|
||||
|
||||
<text x="640" y="538" class="grn">2.</text>
|
||||
<text x="680" y="538" class="txt">Calculate offset</text>
|
||||
|
||||
<text x="640" y="568" class="grn">3.</text>
|
||||
<text x="680" y="568" class="txt">Patch .bin in HxD</text>
|
||||
|
||||
<text x="640" y="598" class="grn">4.</text>
|
||||
<text x="680" y="598" class="txt">uf2conv.py + flash</text>
|
||||
|
||||
<!-- Key Takeaways -->
|
||||
<rect x="40" y="650" width="1120" height="130" rx="8" class="pnl"/>
|
||||
<text x="600" y="688" text-anchor="middle" class="sub">Takeaways</text>
|
||||
|
||||
<rect x="60" y="708" width="340" height="50" rx="4" fill="#0a0a0f" stroke="#ff0040" stroke-width="1"/>
|
||||
<text x="230" y="740" text-anchor="middle" class="red">42 -> 43 (1 byte)</text>
|
||||
|
||||
<rect x="420" y="708" width="340" height="50" rx="4" fill="#0a0a0f" stroke="#00ff41" stroke-width="1"/>
|
||||
<text x="590" y="740" text-anchor="middle" class="grn">XOR 1->0 (invert)</text>
|
||||
|
||||
<rect x="780" y="708" width="360" height="50" rx="4" fill="#0a0a0f" stroke="#ffaa00" stroke-width="1"/>
|
||||
<text x="960" y="740" text-anchor="middle" class="amb">offset = addr - base</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |