3.01 Sequential Execution, Conditional Branches & ARM Cortex-M Pipeline Behavior
💻 1. Annotated Source Code
#include <iostream> using namespace std; int main() { int age; age = 17; cout << "Your age is: " << age << endl; if (age >= 16) { cout << "You can drive!" << endl; } else { cout << "You cannot drive yet!" << endl; } for (int i = 1; i <= age; i++) { cout << "Happy birthday!" << endl; } return 0; }
📐 2. Architecture & UML Class Model
📚 3. Core C++ Concepts Deep-Dive
1. Sequential Execution vs Control Flow Modification
By default, the CPU Program Counter (PC) increments sequentially by 2 or 4 bytes after each instruction fetch. Control statements (if, while, for, switch) modify the PC to jump to non-consecutive memory addresses.
2. Conditional Branch Assembly Instructions
On ARM processors, comparisons set condition flags (N, Z, C, V) in the APSR register; conditional branch instructions (BEQ, BNE, BGT, BLT) jump based on these flag states.
⚡ 4. Embedded Systems & Hardware Reality
1. CPU Pipeline Flushes & Branch Penalties
Modern microcontrollers (such as ARM Cortex-M7 with a 6-stage superscalar pipeline) fetch instructions ahead of execution. When a conditional branch is taken unpredictably, the prefetched pipeline instructions must be discarded (flushed), wasting 3 to 7 clock cycles.
💡 5. Production-Ready Embedded Refactoring
Branch-predictable condition ordering (most likely path first):
#include <cstdint> // Optimize for the 99.9% common case (heartbeat healthy) void evaluateHeartbeat(uint32_t missed_ticks) noexcept { if (missed_ticks == 0) [[likely]] { // Fast path: CPU pipeline runs straight through! return; } // Rare fault path triggerSafetyShutdown(); }
📝 Knowledge Verification Quiz
Test your understanding of the C++ concepts and embedded microcontroller trade-offs covered in this guide. Click any option for instant feedback.
[[likely]] and [[unlikely]] (C++20) guide the compiler's code layout to align the most frequent path for sequential execution.