mirror of
https://github.com/mytechnotalent/Embedded-Hacking.git
synced 2026-08-09 04:16:18 +02:00
186 lines
8.6 KiB
Markdown
186 lines
8.6 KiB
Markdown
# Week 7 Quiz: Constants, I²C, Structs, and String 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 `#define FAV_NUM 42` and `const int OTHER_FAV_NUM = 1337` in terms of how they appear in the compiled binary?
|
||
|
||
A) `#define` appears as `movs r1, #0x2a` (16-bit Thumb) and `const` appears as `movw r1, #0x539` (32-bit Thumb-2) — both are instruction immediates because the compiler optimized away the const variable
|
||
B) `#define` creates a value in the `.data` section; `const` creates a value in the `.rodata` section
|
||
C) `#define` is replaced by the preprocessor so the value appears as an immediate in instructions; `const` always creates a real variable loaded from flash via `ldr`
|
||
D) `#define` values are stored in SRAM; `const` values are stored in flash
|
||
|
||
> 📖 **Reference:** Week 7, Part 9, Step 12 – "Analyze #define vs const in Assembly" (Both end up as instruction immediates: `movs r1, #0x2a` for FAV_NUM and `movw r1, #0x539` for OTHER_FAV_NUM. The compiler optimized the `const` because `&OTHER_FAV_NUM` is never taken.)
|
||
|
||
**Correct Answer: A**
|
||
|
||
---
|
||
|
||
### Question 2
|
||
I²C uses two wires for communication. What are they called and what is each used for?
|
||
|
||
A) TX (transmit data) and RX (receive data)
|
||
B) SDA (serial data) and SCL (serial clock)
|
||
C) MOSI (master out) and MISO (master in)
|
||
D) VCC (power) and GND (ground)
|
||
|
||
> 📖 **Reference:** Week 7, Part 2 – "The Two I²C Wires" table (SDA = Serial Data, SCL = Serial Clock)
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 3
|
||
Why do I²C bus lines require pull-up resistors?
|
||
|
||
A) To limit current and protect the devices from damage
|
||
B) I²C uses open-drain signals — devices can only pull lines LOW, so pull-ups are needed to bring lines back HIGH
|
||
C) The pull-ups provide power to the I²C slave devices
|
||
D) Pull-ups increase the data transfer speed by reducing line capacitance
|
||
|
||
> 📖 **Reference:** Week 7, Part 2 – "Why Pull-Up Resistors?" (I²C uses open-drain signals; devices can only pull LOW, pull-ups bring lines back to HIGH)
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 4
|
||
The `i2c1_inst` struct in SRAM at address `0x2000062c` contains two members. What are they?
|
||
|
||
A) `sda_pin` = 2 and `scl_pin` = 3 (the GPIO pin numbers)
|
||
B) `hw` = `0x40098000` (pointer to hardware registers) and `restart_on_next` = `false`
|
||
C) `address` = `0x27` (LCD I²C address) and `baud_rate` = `100000`
|
||
D) `tx_buffer` and `rx_buffer` (data transfer buffers)
|
||
|
||
> 📖 **Reference:** Week 7, Part 8, Step 9 and Part 9, Step 13 – examining `i2c1_inst` at `0x2000062c` shows `0x40098000` (hw pointer) and `0x00000000` (restart_on_next = false)
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 5
|
||
In the Thumb instruction `movs r1, #0x2a`, the bytes in the binary are `2A 21`. If you want to change FAV_NUM from 42 to 99, what bytes would you write?
|
||
|
||
A) `63 21` — because 99 in hex is `0x63` and the opcode `21` stays the same
|
||
B) `99 21` — because 99 in decimal is written directly
|
||
C) `21 63` — because the opcode comes first in big-endian format
|
||
D) `63 00` — because the opcode changes when the value changes
|
||
|
||
> 📖 **Reference:** Week 7, Part 10, Step 17 – "How Thumb encoding works" (immediate value is the first byte, opcode `21` is the second; `movs r1, #imm8`)
|
||
|
||
**Correct Answer: A**
|
||
|
||
---
|
||
|
||
### Question 6
|
||
The `movw r1, #1337` instruction at `0x10000296` encodes the value 1337 (`0x539`) in a 32-bit Thumb-2 instruction. The raw bytes are `40 F2 39 51`. Where is the lower 8 bits of the immediate value (`0x39`) located?
|
||
|
||
A) Byte 0 (`0x40`) — the immediate is always in the first byte of the instruction
|
||
B) Byte 2 (`0x39`) — the imm8 field is in the third byte (low byte of the second halfword)
|
||
C) Byte 3 (`0x51`) — the immediate is stored in the last byte along with the register
|
||
D) The value `0x539` is stored as a separate 4-byte word in the literal pool, not in the instruction
|
||
|
||
> 📖 **Reference:** Week 7, Part 10, Step 18 – "Understand the Encoding" (the `movw` encoding diagram shows Byte 2 = `0x39` = imm8 field, which holds the lower 8 bits of the immediate value)
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 7
|
||
When patching the LCD string "Reverse" to "Exploit" in the binary, why must the replacement string be the same length?
|
||
|
||
A) The LCD hardware only accepts strings of exactly 7 characters
|
||
B) The replacement must fit within the allocated bytes — a longer string would overwrite adjacent data (like the "Engineering" string stored immediately after)
|
||
C) The Thumb instruction set cannot encode string addresses of different lengths
|
||
D) The Pico SDK validates string lengths at boot and rejects changes
|
||
|
||
> 📖 **Reference:** Week 7, Part 10, Step 19 – "IMPORTANT: The new string must be the same length as the original!" and Key Takeaway 8
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 8
|
||
The LCD string "Reverse" is located at address `0x10003ee8`. What is the correct file offset in the `.bin` file?
|
||
|
||
A) `0x3EE8` — subtract the base address `0x10000000`
|
||
B) `0x10003EE8` — the file offset is the same as the memory address
|
||
C) `0x7DD0` — multiply by 2 because the binary uses 16-bit alignment
|
||
D) `0x3EE0` — round down to the nearest 16-byte boundary
|
||
|
||
> 📖 **Reference:** Week 7, Part 10, Step 16 – "Calculate the File Offset" (file_offset = address − 0x10000000; `0x10003ee8` → `0x3EE8`)
|
||
|
||
**Correct Answer: A**
|
||
|
||
---
|
||
|
||
### Question 9
|
||
What does the macro chain `I2C_PORT` → `i2c1` → `&i2c1_inst` → `hw` → `0x40098000` represent?
|
||
|
||
A) The sequence of function calls during I²C initialization
|
||
B) The path from a high-level macro in your code to the physical I²C1 hardware registers, through preprocessor expansion, pointer dereference, and struct member access
|
||
C) The I²C data transmission protocol (start, address, data, stop)
|
||
D) The order in which the compiler optimizes I²C-related code
|
||
|
||
> 📖 **Reference:** Week 7, Part 4 – "The Macro Chain" diagram and Part 9, Step 13 – tracing the chain from code to `0x40098000`
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
### Question 10
|
||
The compiler transforms `gpio_pull_up(2)` into a call to `gpio_set_pulls(2, 1, 0)`. What does each argument represent?
|
||
|
||
A) Pin number, pull-up resistance value in kΩ, pull-down resistance value in kΩ
|
||
B) Pin number, enable pull-up (true), enable pull-down (false)
|
||
C) SDA pin, SCL pin, I²C bus number
|
||
D) Pin number, direction (1 = input), initial value (0 = LOW)
|
||
|
||
> 📖 **Reference:** Week 7, Key Takeaway 10 – "Compiler optimization changes code — `gpio_pull_up` becomes `gpio_set_pulls`" and Week 6 reference (inlined function: pin, up=true, down=false)
|
||
|
||
**Correct Answer: B**
|
||
|
||
---
|
||
|
||
## Answer Key
|
||
|
||
1. A - Both `#define` and `const` appear as instruction immediates (`movs` and `movw`) because the compiler optimized the `const` — its address is never taken
|
||
2. B - SDA (Serial Data) carries data; SCL (Serial Clock) provides timing
|
||
3. B - I²C open-drain signals can only pull LOW; pull-ups return lines to HIGH
|
||
4. B - `hw` = `0x40098000` (hardware register pointer) and `restart_on_next` = false
|
||
5. A - Change `2A` to `63` (99 in hex); opcode `21` (`movs r1, #imm8`) remains unchanged
|
||
6. B - The imm8 field (lower 8 bits of the immediate) is in the third byte of the 4-byte `movw` instruction
|
||
7. B - A longer string would overwrite adjacent data in the `.rodata` section
|
||
8. A - File offset = address − base = `0x10003EE8` − `0x10000000` = `0x3EE8`
|
||
9. B - The chain traces from a C macro through pointer indirection to physical hardware register addresses
|
||
10. B - Arguments are: GPIO pin number, pull-up enable (true), pull-down enable (false)
|
||
|
||
---
|
||
|
||
## Scoring Guide
|
||
|
||
- **10 correct**: Excellent! You have a strong grasp of Week 7 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 7 material again and try the practice exercises
|
||
|
||
---
|
||
|
||
## Topics Covered
|
||
|
||
This quiz tests your understanding of:
|
||
- `#define` preprocessor macros vs `const` variables: compiler optimization of const to immediates
|
||
- I²C communication protocol: SDA/SCL wires and pull-up resistor requirements
|
||
- Pico SDK `i2c_inst_t` struct layout and hardware register pointers
|
||
- Thumb instruction encoding: `movs rD, #imm8` and `movw rD, #imm16` byte layouts
|
||
- 32-bit Thumb-2 `movw` encoding: imm8 field location in the instruction
|
||
- String patching constraints: same-length rule and adjacent data corruption risk
|
||
- File offset calculation: memory address minus base address `0x10000000`
|
||
- SDK macro chain: from `I2C_PORT` to `0x40098000` hardware registers
|
||
- Compiler optimization: `gpio_pull_up` inlined as `gpio_set_pulls`
|