mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-08-10 13:10:32 +02:00
Updated DS refs
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
# Week 6 Quiz: Static Variables, GPIO Input, and Binary Patching
|
||||
|
||||
## Instructions
|
||||
Choose the best answer for each question. There is only one correct answer per question.
|
||||
|
||||
---
|
||||
|
||||
## Questions
|
||||
|
||||
### Question 1
|
||||
What is the key difference between a **static local variable** and a **regular local (automatic) variable** in C?
|
||||
|
||||
A) Static variables are stored on the stack; automatic variables are stored in flash
|
||||
B) Static variables retain their value between function calls; automatic variables are re-created each time
|
||||
C) Static variables can only be used in `main()`; automatic variables can be used anywhere
|
||||
D) Static variables are always initialized to a random value; automatic variables default to 0
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 1 – "Static Variables vs Regular Variables" (static variables persist across function calls and loop iterations; automatic variables are re-created each time)
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 2
|
||||
Where in memory is an initialized static variable stored on the Pico 2?
|
||||
|
||||
A) On the stack (high RAM addresses growing downward)
|
||||
B) In the `.text` section alongside executable code
|
||||
C) In the `.data` section — initial values in flash, runtime copy in SRAM
|
||||
D) In CPU registers only — static variables are never stored in RAM
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 3 – "Compiler Optimizations" and Part 7 – "Analyze the Static Variable" (static variable lives at fixed RAM address `0x200005a8` in the `.data` section)
|
||||
|
||||
**Correct Answer: C**
|
||||
|
||||
---
|
||||
|
||||
### Question 3
|
||||
Why did the compiler optimize away `regular_fav_num` and replace it with a constant `movs r1, #0x2a` in the binary?
|
||||
|
||||
A) The compiler detected that `regular_fav_num` is never modified after initialization
|
||||
B) The variable is too small (8 bits) for the compiler to allocate memory
|
||||
C) The variable is assigned 42, printed, then incremented — but the increment has no observable effect since the variable is re-created each loop iteration
|
||||
D) ARM processors cannot store local variables in RAM
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 7, Step 13 – "Analyze the Regular Variable" (compiler optimized away the variable because its value is always 42 when printed; the post-print increment has no observable effect)
|
||||
|
||||
**Correct Answer: C**
|
||||
|
||||
---
|
||||
|
||||
### Question 4
|
||||
What does the `ubfx r3, r3, #0xf, #0x1` instruction do?
|
||||
|
||||
A) Stores the byte in r3 at GPIO address 0xF
|
||||
B) Extracts bit 15 (a single bit) from r3 and stores the result in r3
|
||||
C) Sets all bits in r3 except bit 15
|
||||
D) Performs an unsigned division of r3 by 15
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 7, Step 15 – "Analyze the GPIO Logic" (table: `ubfx r3,r3,#0xf,#0x1` extracts bit 15, which is GPIO 15 = button)
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 5
|
||||
A pull-up resistor on GPIO 15 means the pin reads HIGH when the button is **not** pressed. What instruction does the compiler use to implement the `!gpio_get(BUTTON_GPIO)` inversion?
|
||||
|
||||
A) `sub r3, r3, #0x1` — subtracts 1 from the button state
|
||||
B) `mvn r3, r3` — performs a bitwise NOT on all 32 bits
|
||||
C) `eor r3, r3, #0x1` — XOR with 1 to flip the least significant bit
|
||||
D) `cmp r3, #0x0` followed by a conditional branch
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 7, Step 15 – GPIO logic table (`eor r3,r3,#0x1` implements the ternary operator `? 0 : 1` by XORing with 1)
|
||||
|
||||
**Correct Answer: C**
|
||||
|
||||
---
|
||||
|
||||
### Question 6
|
||||
The static variable `static_fav_num` is a `uint8_t`. What happens when it reaches 255 and is incremented by 1?
|
||||
|
||||
A) The program crashes with an overflow exception
|
||||
B) The value wraps around to 0 due to unsigned integer overflow
|
||||
C) The value becomes 256 because the compiler promotes it to `uint16_t`
|
||||
D) The value stays at 255 (saturation arithmetic)
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 5, Step 5 – "Watch for Overflow" (output shows: 254, 255, 0, 1 — demonstrating unsigned integer wrap-around)
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 7
|
||||
When patching the `movs r1, #0x2a` instruction at address `0x10000264`, what is the correct file offset in the `.bin` file?
|
||||
|
||||
A) `0x10000264` — binary addresses and file offsets are the same
|
||||
B) `0x264` — subtract the base address `0x10000000` from the instruction address
|
||||
C) `0x265` — the immediate value is in the second byte of the instruction
|
||||
D) `0x002640` — multiply by 16 because hex addresses use nibbles
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 8, Step 18 – “Calculate the File Offset” (file_offset = address − 0x10000000; 0x10000264 → 0x264)
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 8
|
||||
In the Thumb instruction `movs r1, #0x2a`, the bytes in the binary are `2A 21`. What does each byte represent?
|
||||
|
||||
A) `2A` is the register number; `21` is the value
|
||||
B) `2A` is the immediate value (42); `21` is the opcode for `movs r1, #imm8`
|
||||
C) `2A 21` is the two-byte little-endian encoding of the value 8490
|
||||
D) `2A` is the opcode; `21` is the register and immediate combined
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 8, Step 19 – "How Thumb encoding works" callout (immediate value is the first byte, opcode `21` is the second byte)
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 9
|
||||
The SDK function `gpio_pull_up(15)` does not appear in the disassembly. Instead, GDB shows a call to `gpio_set_pulls(15, 1, 0)`. Why?
|
||||
|
||||
A) `gpio_pull_up` is a deprecated function that was removed from the SDK
|
||||
B) The compiler inlined `gpio_pull_up` — it's a small wrapper that calls `gpio_set_pulls` with `up=true, down=false`
|
||||
C) The linker renamed the function to avoid symbol conflicts
|
||||
D) GDB incorrectly resolves the function name
|
||||
|
||||
> 📖 **Reference:** Week 6, Part 3 – "Function Inlining" and Part 6, Step 6 – disassembly showing `bl gpio_set_pulls` with args `r0=15, r1=1, r2=0`
|
||||
|
||||
**Correct Answer: B**
|
||||
|
||||
---
|
||||
|
||||
### Question 10
|
||||
You want to permanently change the static variable's initial value from 42 to 100 in the binary. Which approach is correct?
|
||||
|
||||
A) Modify the `movs r1, #0x2a` instruction at `0x10000264` because that is where the static variable is initialized
|
||||
B) Use GDB to `set *(char*)0x200005a8 = 100` — this permanently changes the flash
|
||||
C) Find the initialization value in the `.data` section of flash, calculate its file offset, and patch it from `0x2A` to `0x64` in the hex editor
|
||||
D) Change the `push {r4, lr}` instruction to load 100 into r4 before main starts
|
||||
|
||||
> 📖 **Reference:** Week 6, Practice Exercise 1 – "Change Static Variable Initial Value" (the initial value lives in the `.data` section in flash; the startup code copies it to RAM before `main()` runs)
|
||||
|
||||
**Correct Answer: C**
|
||||
|
||||
---
|
||||
|
||||
## Answer Key
|
||||
|
||||
1. B - Static variables persist between function calls; automatic variables are re-created each time
|
||||
2. C - The `.data` section holds initial values in flash; they are copied to SRAM at startup
|
||||
3. C - The post-print increment has no observable effect because the variable resets each loop iteration
|
||||
4. B - UBFX (Unsigned Bit Field Extract) extracts bit 15 (one bit) — the button GPIO state
|
||||
5. C - `eor.w r3, r3, #1` flips the least significant bit, implementing logical NOT for a single-bit value
|
||||
6. B - `uint8_t` wraps from 255 to 0 — unsigned overflow is well-defined in C
|
||||
7. B - File offset = address − base (`0x10000264` − `0x10000000` = `0x264`)
|
||||
8. B - In Thumb `movs rD, #imm8`, the first byte is the immediate, the second byte is the opcode
|
||||
9. B - The compiler inlines `gpio_pull_up` as a call to `gpio_set_pulls` with `up=true, down=false`
|
||||
10. C - Static variable initial values live in the `.data` section of flash and must be patched there
|
||||
|
||||
---
|
||||
|
||||
## Scoring Guide
|
||||
|
||||
- **10 correct**: Excellent! You have a strong grasp of Week 6 concepts
|
||||
- **8-9 correct**: Very good! Review the topics you missed
|
||||
- **6-7 correct**: Good start. Go back and review the key concepts
|
||||
- **5 or fewer**: Review the Week 6 material again and try the practice exercises
|
||||
|
||||
---
|
||||
|
||||
## Topics Covered
|
||||
|
||||
This quiz tests your understanding of:
|
||||
- Static vs automatic (local) variables and their storage duration
|
||||
- `.data` section: flash initialization values copied to SRAM at startup
|
||||
- Compiler optimizations: dead code elimination and constant propagation
|
||||
- UBFX (Unsigned Bit Field Extract) for reading individual GPIO pins
|
||||
- XOR (EOR) for implementing logical NOT on single-bit values
|
||||
- Unsigned integer overflow and `uint8_t` wrap-around behavior
|
||||
- File offset calculation: address minus base address `0x10000000`
|
||||
- Thumb instruction encoding: `movs rD, #imm8` byte layout
|
||||
- Function inlining: `gpio_pull_up` → `gpio_set_pulls`
|
||||
- Binary patching strategy for static variable initial values
|
||||
Reference in New Issue
Block a user