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:

  1. Programmer writes myprogram.c.
  2. Compiler processes the entire file — detects and reports any errors.
  3. If no errors: produces myprogram.exe (machine code for the target processor).
  4. User runs myprogram.exe directly — 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.