An assembler translates assembly language — a low-level, human-readable mnemonic code — into machine code, with a near one-to-one mapping between instructions. A compiler translates an entire high-level language program into machine code in one pass before execution. Both produce machine-executable output, but from very different starting points.
Why must programs be translated at all?
The CPU can only execute machine code — binary instructions encoded as sequences of 0s and 1s. No human writes programs directly in machine code (though Turing himself had to, for the Manchester Mark 1). Higher-level representations — assembly mnemonics, Python, Java — make programming manageable for human beings, but they must all eventually be converted into the binary that the processor actually runs. Translators perform this conversion.
There are three main types of translator: assemblers, compilers, and interpreters. They differ in their input language and translation strategy.
What is an assembler and what does it translate?
An assembler takes assembly language as input and produces machine code as output.
Assembly language uses short, memorable text codes — called mnemonics — that correspond almost directly to machine code instructions. Each mnemonic typically represents a single machine code operation.
Example assembly instruction (x86 style):
MOV AX, 5 ; Load the value 5 into register AX
ADD AX, BX ; Add the value in register BX to AX
The assembler converts each of these one or two-word instructions into the specific binary pattern that the processor understands. The translation is one-to-one: one assembly instruction → one machine code instruction (or occasionally a small, fixed number). There is no optimisation or restructuring.
Assembly language characteristics:
| Feature | Detail |
|---|---|
| Level | Low-level — close to hardware |
| Input to assembler | Mnemonic instructions, labels, directives |
| Output from assembler | Machine code (binary / object file) |
| Portability | Processor-specific — ARM assembly differs from x86 |
| Who uses it | Embedded systems engineers, OS kernel developers |
What is a compiler and what does it translate?
A compiler takes an entire high-level language program (such as C, C++, or Swift) as input and translates the whole program into machine code (or an intermediate representation) before execution begins. The resulting machine code file can then be run independently, without the original source code.
Key properties of compilation:
- The entire source file is read before any output is produced.
- The compiler performs lexical analysis (breaking source into tokens), syntax analysis (checking grammar), semantic analysis (checking meaning), and code generation.
- The compiler can optimise the output — reordering instructions, eliminating redundant code — producing machine code that runs faster than a direct translation would.
- Error reporting: all syntax errors are reported before any execution occurs.
Example compilation cycle:
- Programmer writes
myprogram.c. - Compiler processes the entire file — detects and reports any errors.
- If no errors: produces
myprogram.exe(machine code for the target processor). - User runs
myprogram.exedirectly — the compiler is not needed again.
How does an assembler differ from a compiler?
| Feature | Assembler | Compiler |
|---|---|---|
| Input language | Assembly language (low-level) | High-level language (Python, C, etc.) |
| Translation ratio | ~1:1 (one mnemonic → one instruction) | Many-to-many (one statement → many instructions) |
| Optimisation | Minimal | Significant — the compiler restructures code |
| Output | Machine code / object file | Machine code / executable |
| Source language abstraction | Very close to hardware | Far from hardware |
| Portability of source | Not portable (processor-specific) | Portable (same source compiles for different CPUs) |
The fundamental difference is abstraction distance: assembly language is one small step above machine code; high-level languages are many steps above.
How does an interpreter fit into the picture?
An interpreter translates and executes a high-level language one statement at a time at runtime, without producing a standalone executable. Python, when run interactively, uses an interpreter.
| Feature | Assembler | Compiler | Interpreter |
|---|---|---|---|
| Translates before or during execution | Before | Before | During (at runtime) |
| Produces a standalone executable | Yes | Yes | No |
| Speed of translated program | Very fast | Fast | Slower (translation overhead at runtime) |
| Error detection | All before execution | All before execution | Stops at first error encountered |
| Ease of debugging | Difficult | Moderate | Easy (runs line by line) |
Compiled programs run faster because translation is done once in advance. Interpreted programs are easier to debug and more portable, but slower.
When would a programmer choose each translator?
| Use case | Best translator | Reason |
|---|---|---|
| Operating system kernel | Assembler | Direct hardware control; maximum speed; tiny code size |
| Embedded microcontroller with limited memory | Assembler | No memory to spare for a runtime environment |
| Commercial application (game, word processor) | Compiler | Fast execution; portable source code |
| School programming lessons or rapid prototyping | Interpreter | Immediate feedback; no compilation step |
| JavaScript in a web browser | Just-in-time compiler (hybrid) | Compiled at runtime for speed, interpreted for portability |
Frequently asked questions
Is Python interpreted or compiled?
Python uses an interpreter in the conventional sense — running python myprogram.py translates and executes the program line by line. However, Python also compiles source code to an intermediate format called bytecode (.pyc files), which is then executed by the Python virtual machine. This is sometimes called a "hybrid" approach. For GCSE purposes, Python is described as an interpreted language.
Can the same language use both a compiler and an interpreter?
Yes. Many languages have both compiled and interpreted implementations. C is almost always compiled; Python is usually interpreted; Java compiles to bytecode which is then interpreted by the JVM. The language and the translator are separate concepts. The choice of translator affects performance and portability, not the language syntax itself.
Why is assembly language still used today if high-level languages exist?
Assembly language is still used in contexts where performance and hardware control are critical and there is no room for the overhead that a compiler or runtime environment introduces. Operating system bootloaders, device drivers, real-time embedded systems (such as pacemakers and aircraft control systems), and hand-optimised graphics routines all use assembly in parts. In these situations, the programmer must control exactly which instruction the processor executes and when.
What is an object file produced by a compiler?
When a compiler processes one source file, it may produce an object file (.o or .obj) rather than a complete executable. Object files contain machine code but with unresolved references to external functions or libraries. A second program — the linker — combines multiple object files and links in library code to produce the final executable. This separation allows large programs to be compiled in parts and linked together, which is more efficient than recompiling everything when one file changes.
Explore programming languages and how they work under the hood with Professor Turing's GCSE tutoring at aitutors.me.