How Programming Languages Are Converted into Machine Code
Source: Dev.to
Introduction
Programming lets us build calculators, websites, AI agents, and more. However, machines don’t understand high‑level programming languages directly; they only understand binary code (0s and 1s). Therefore, each language must be compiled or interpreted before execution.
Why Binaries Differ Across Platforms
-
CPU architecture – Each CPU has its own instruction set.
- Intel/AMD: x86 / x86‑64
- Apple M1/M2: ARM64
- Many Android devices: ARM
-
Operating system – Even on the same CPU, Windows, macOS, and Linux provide different system APIs and library formats.
Consequences
- A Windows executable compiled for an Intel x86 CPU won’t run on a Mac with an ARM CPU.
- A Windows program that calls Windows‑specific APIs (e.g.,
CreateFile()) won’t run on macOS or Linux, which useopen(). - Library formats differ: Windows uses
.dll, macOS uses.dylib, and Linux uses.so. A Windows.execannot locate the required libraries on macOS.
Analogy
Think of a recipe written in English that references tools only found in a Windows kitchen. Giving that recipe to a chef in a Mac kitchen fails because:
- The steps are in a different “language” (CPU instruction mismatch).
- The required tools don’t exist (OS system‑call mismatch).
- Ingredients are stored differently (library mismatch).
Thus, programs must be compiled separately for each target platform.
Compilation Strategies
Direct Compilation
| Languages | Output |
|---|---|
| C, C++, Rust, Go | Machine code for a specific CPU + OS |
Flow: Source Code → Compiler → Machine Code (Windows / macOS / Linux)
- Pros: Fastest execution.
- Cons: Requires a separate binary for each platform.
Bytecode + Virtual Machine
| Languages | Output |
|---|---|
| Java, Kotlin, C#, Python | Bytecode → VM → Machine Code |
Flow: Source → Bytecode → Virtual Machine (VM) → Machine Code
- Pros: Runs on any OS with a compatible VM.
- Cons: Slightly slower than native code.
Interpreted + JIT
| Languages | Output |
|---|---|
| JavaScript, Python (PyPy), Ruby | Interpreter/JIT → Machine Code |
Flow: Source → Interpreter/JIT → Machine Code
- JIT (Just‑In‑Time) compilation improves performance over pure interpretation.
Transpiled
| Languages | Output |
|---|---|
| TypeScript, Elm | Transpile → JavaScript → JIT → Machine Code |
Flow: Source → Transpiler → Target Language (e.g., JavaScript) → JIT → Machine Code
Key Takeaway
We write code in human‑friendly languages, but CPUs and operating systems understand only their own binary “dialects.” Compilers, interpreters, virtual machines, and JIT engines translate our code into a form the machine can execute.