Computer & OS Fundamentals · beginner · ~10 min

How a computer runs a program

Trace what happens from source code to a running process the CPU executes.

Overview

The CPU runs a fetch-decode-execute loop over machine code in memory. Compiled code becomes machine code directly; interpreted code is run by an interpreter. Code and data share memory.

Why it matters

Exploitation, shellcode, and reverse engineering all operate at the level of "the CPU executes whatever the program counter points at." This mental model is why control-flow hijacks like return-address overwrites work.

Core concepts

Fetch-decode-execute. The CPU's core loop. Program counter. Holds the address of the next instruction. Machine code. What actually executes, whether produced ahead of time (compiled) or driven by an interpreter. Von Neumann. Code and data live in the same memory — the root of memory-safety risk.

Lesson

A program is just data until the CPU executes it. Understanding that path is the foundation for everything from debugging to exploitation.

The fetch-decode-execute cycle

The CPU repeats one loop billions of times a second:

  1. Fetch the next instruction from memory (its address is in the program counter).
  2. Decode what the instruction means.
  3. Execute it — arithmetic, a memory read/write, or a jump.

From source to execution

For a compiled language like C: source → compiler → machine code → loaded into memory → executed. For interpreted languages, an interpreter (itself a compiled program) reads and runs the source. Either way, what the CPU runs is machine code.

Why a pentester cares

Memory-corruption bugs, shellcode, and reverse engineering all live at this layer. When you understand that code and data share the same memory and the CPU blindly executes whatever the program counter points at, you understand why overwriting a return address can hijack execution — the core idea behind classic exploitation.

Summary

A computer executes machine code via a fetch-decode-execute loop, with the program counter choosing what runs next. Because code and data share memory, controlling what the program counter points at means controlling execution — the seed of memory exploitation.