Machine Code
The exact sequence of binary instructions that a processor reads and executes directly — the lowest level of programming, where every instruction is a pattern of 0s and 1s that the hardware understands without translation.
What is it?
Machine code is the only language a CPU actually understands. Every other programming language — Python, JavaScript, Java, C — eventually becomes machine code before the processor can do anything with it.1
Each instruction is a binary pattern that tells the CPU to perform one tiny operation: move a number from one place to another, add two numbers, compare a value to zero, jump to a different instruction. These operations are absurdly simple individually. The power comes from executing billions of them per second.
Machine code is specific to a processor family. Intel and AMD processors understand x86 machine code. Apple’s M-series chips understand ARM machine code. The same program, written in machine code for one processor, will not run on the other — the binary patterns mean different things.2
Assembly language is the human-readable version of machine code.
Instead of writing 10110000 01100001, you write mov al, 61h
— a mnemonic that maps directly to the same instruction. A small
program called an assembler translates assembly back to binary.3
In plain terms
Machine code is the native tongue of the processor. Every other language is a foreign language that needs a translator (compiler or interpreter) to convert it into machine code before the CPU can follow the instructions.
At a glance
From human intent to machine code (click to expand)
graph LR PY[Python<br/>a = 97] -->|interpreter| MC1[Machine code] C[C<br/>char a = 97] -->|compiler| MC2[Machine code] ASM[Assembly<br/>mov al, 61h] -->|assembler| MC3[Machine code] MC1 --> CPU[CPU executes] MC2 --> CPU MC3 --> CPU style MC1 fill:#e74c3c,color:#fff style MC2 fill:#e74c3c,color:#fff style MC3 fill:#e74c3c,color:#fff style CPU fill:#4a9ede,color:#fffKey: All roads lead to machine code. Every language, no matter how high-level, is eventually converted into the binary patterns the CPU reads.
How does it work?
Instruction format
Each machine code instruction has two parts:4
Opcode — the operation to perform (add, move, compare, jump). Operands — the data or memory addresses the operation acts on.
For example, in x86 machine code, 10110000 01100001 breaks
down as:
10110= opcode for “move immediate value into register”000= register AL (the target)01100001= the value 97 (the number to move)
Think of it like...
A recipe written in code. The opcode is the verb (chop, stir, heat). The operands are the nouns (onions, oil, pan). The processor reads each instruction, identifies the verb and the nouns, and performs the action.
The instruction set
Every processor family defines its own instruction set — the complete list of operations it can perform. x86 has hundreds of instructions. ARM has a smaller, more uniform set.5
This is why machine code is not portable. Each instruction set is a different “language” with different opcodes. Code compiled for x86 is meaningless to an ARM processor.
Assembly: the readable layer
Assembly language provides human-readable mnemonics for machine code instructions:
| Machine code | Assembly | Meaning |
|---|---|---|
10110000 01100001 | mov al, 61h | Put 97 in register AL |
00000100 00000010 | add al, 2 | Add 2 to register AL |
11001101 00100001 | int 21h | Call operating system |
Assembly and machine code have a one-to-one relationship. Each assembly instruction maps to exactly one machine code instruction. The assembler performs a direct substitution — no optimisation, no interpretation.3
Adding two numbers in assembly vs machine code
Assembly (x86):
mov eax, 5 ; put 5 in register EAX mov ebx, 3 ; put 3 in register EBX add eax, ebx ; add EBX to EAX (result: 8)Machine code (hex representation):
B8 05 00 00 00 BB 03 00 00 00 01 D8Three instructions. Each one moves or adds a number. This is the level of granularity the CPU works at.
Why do we use it?
Key reasons
1. It is the only option. The CPU cannot execute anything else. Every program, in every language, ultimately becomes machine code.
2. Maximum performance. Machine code runs with zero translation overhead. Critical code in operating systems, game engines, and embedded systems is sometimes written in assembly (and thus directly maps to machine code) for this reason.
3. Maximum control. Machine code gives you direct access to every hardware capability. When you need precise timing, exact memory layout, or specific hardware features, this is the level that provides it.
When do we use it?
- You almost never write machine code or assembly directly in modern development
- Operating system kernels — the most performance-critical parts of Linux, Windows, and macOS include assembly code
- Embedded systems — devices with extreme constraints (medical implants, satellite controllers) sometimes require hand-written assembly
- Reverse engineering — security researchers read machine code to analyse malware or find vulnerabilities
- Understanding — knowing machine code exists helps you understand what compilers and interpreters actually produce
Rule of thumb
If you are not building an operating system, writing firmware, or doing security research, you will never write machine code. But understanding that it exists — and that it is what your code becomes — changes how you think about every other language.
How can I think about it?
The native language
Machine code is the processor’s native language. When you write Python, you are speaking through a translator (the interpreter). When you write C, you hire a translator in advance (the compiler) to produce a document in the native language.
The processor only reads the native language. It does not know or care what language you originally wrote in. The quality of the translation matters — a good compiler produces efficient machine code, a bad one produces bloated code — but the processor just follows whatever instructions arrive.
The sheet music
Machine code is like sheet music for a mechanical piano. The piano (CPU) reads the punched holes (binary patterns) and plays exactly what is written. It cannot improvise. It cannot interpret artistic intent. It plays the holes.
A composer (programmer) could punch the holes directly, but that is tedious and error-prone. Instead, they write musical notation (a high-level language) and use a transcription machine (compiler) to produce the punched roll. The piano does not know the difference — it just plays the holes.
Concepts to explore next
| Concept | What it covers | Status |
|---|---|---|
| binary | The number system machine code is written in | complete |
| compiler | How high-level languages are translated to machine code | complete |
| interpreter | An alternative translation strategy — line by line | complete |
| abstraction-layers | Why we built layers above machine code | complete |
Check your understanding
Test yourself (click to expand)
- Explain why machine code is specific to a processor family. What happens if you try to run x86 machine code on an ARM processor?
- Describe the two parts of a machine code instruction (opcode and operands) and what each does.
- Distinguish between machine code and assembly language. What is the relationship between them?
- Interpret this: a Python script runs on both a Windows PC (x86) and a MacBook (ARM). If machine code is processor-specific, how is this possible?
- Connect machine code to abstraction-layers: why did programmers stop writing machine code directly?
Where this concept fits
Position in the knowledge graph
graph TD AL[Abstraction Layers] --> MC[Machine Code] AL --> COMP[Compiler] AL --> INTP[Interpreter] BIN[Binary] --> MC style MC fill:#4a9ede,color:#fffRelated concepts:
- binary — the number system machine code is expressed in
- compiler — translates high-level code into machine code ahead of time
- interpreter — translates and executes code line by line, ultimately producing machine code operations
Sources
Further reading
Resources
- Introduction to Programming Languages — LearnCpp’s clear walkthrough from machine code up through high-level languages
- x86 Assembly Guide — University of Virginia’s concise reference for understanding x86 assembly
- From 1+1 in Assembly to LLMs — A walkthrough of the full abstraction ladder with code examples at every level
Footnotes
-
LearnCpp.com. (2024). Introduction to Programming Languages. LearnCpp. ↩
-
Patterson, D. & Hennessy, J. (2020). Computer Organization and Design: The Hardware/Software Interface. 6th ed. Morgan Kaufmann. ↩
-
Wikipedia. (2026). Assembly language. Wikipedia. ↩ ↩2
-
Tanenbaum, A. (2012). Structured Computer Organization. 6th ed. Pearson. ↩
-
ARM vs x86 instruction set comparison. Patterson, D. & Hennessy, J. (2017). Computer Organization and Design: RISC-V Edition. Morgan Kaufmann. ↩
