# Phase 8.2 - First GCC Program ## Context The first compiled program proves your hardware can execute compiler-generated code, not just carefully hand-authored assembly. ## Goals - Compile a tiny C firmware for `rv32im`. - Convert the ELF into a memory image. - Print through UART MMIO from C. ## New Concepts - `-march`: compiler ISA target string. - `-mabi`: ABI selection, here `ilp32` for 32-bit integer/long/pointer. - objcopy: tool that converts ELF into raw binary or other formats. - Disassembly: readable assembly representation of generated machine code. ## How To Think About It Treat the compiler as an external producer of instructions. Your job is to verify that every emitted instruction is implemented or fails loudly. ## Learning Tasks - Compare C source to generated assembly. - Identify every load/store used for UART access. - Confirm no CSR or `fence.i` instructions appear before Phase 9. ## Pitfalls - Using the wrong `-march` and accidentally generating unsupported instructions. - Forgetting `volatile` on MMIO accesses in firmware. - Assuming the compiler will preserve simple-looking loops exactly. ## Tooling And Testing - Always inspect early firmware with objdump. - Build at low optimization first, then compare optimized output later. - Keep firmware small enough to single-step mentally. ## References - GCC RISC-V options: https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Options.html - RISC-V ELF psABI: https://github.com/riscv-non-isa/riscv-elf-psabi-doc - GNU objcopy: https://sourceware.org/binutils/docs/binutils/objcopy.html