- The difference between high-level and low-level programming languages.
- Why machine code and assembly language are both low-level, but not the same.
- Why programs usually need to be translated before they can run.
- How compilers, interpreters and assemblers work, and when to use each one.
A computer program is a set of instructions for a computer to follow. The problem is that humans and processors “think” in very different ways.
Humans prefer code that is readable and close to English or maths. Processors only directly execute very simple binary instructions called machine code.
Source code
Source code is the program text written by a programmer before it has been translated into a form the processor can execute.
The diagram shows the main language levels and the three common types of translator you need for this topic.

Core idea
The processor only executes machine code, so code written in a high-level language or assembly language must be translated or run through a translator.
Programming languages can be classified by how close they are to the hardware.
High-level language
A high-level language is a programming language designed to be easier for humans to read, write and understand. It is less directly tied to the details of a particular processor.
Examples include Python, C#, Java and VB.NET. These languages let you use meaningful variable names, structured statements such as IF, WHILE and FOR, and built-in features such as strings, lists or file handling.
Most computer programs are written in high-level languages because they are quicker to develop, easier to debug and easier to maintain.
Low-level language
A low-level language is a programming language that is close to the hardware and gives the programmer more direct control over processor instructions and memory.
The two low-level languages you need to know are:
- Machine code
- Assembly language
Low-level languages are harder for humans to read and write, but they can give very precise control over hardware.
Here is the main comparison.
| Feature | High-level language | Low-level language |
|---|
| Ease for humans | Easier to read, write and debug | Harder to read, write and debug |
| Closeness to hardware | Further from the hardware | Closer to the hardware |
| Portability | More likely to work on different types of computer after suitable translation | Usually tied to a particular processor or processor family |
| Control | Less direct control over hardware | More direct control over hardware |
| Development speed | Usually faster | Usually slower |
| Typical use | Most general software | Embedded systems, hardware control, performance-critical parts |
Portability
Portability means how easily a program can be moved to and run on different types of computer system.
Choosing a language level
A company is writing a stock-control system for a shop. Should it normally use a high-level or low-level language?
- The program mainly handles data input, calculations, storage and output, rather than directly controlling processor registers or hardware components.
- The company will benefit from code that is easier to read, test, update and maintain over time.
- A high-level language is the better choice because development will be quicker and the program does not need direct low-level hardware control.
Thinking low-level always means better
Low-level languages can be efficient and powerful, but they are not automatically “better”. For most programs, the time saved by using a high-level language is far more important.
Machine code
Machine code is the binary code that a processor can directly execute.
Machine code is written using binary, which uses only the digits 0 and 1. Each machine-code instruction tells the processor to perform a very small operation, such as moving data, adding values or jumping to another instruction.
Machine code is processor-specific. This means that each type of processor, or family of processors, has its own machine-code instruction set.
Instruction set
An instruction set is the set of machine-code instructions that a particular processor can understand and execute.
For example, a machine-code program written for one processor family will not necessarily run on a different processor family.
Machine code is not universal
Do not describe machine code as “the same for all computers”. It is binary, but the meaning of each binary instruction depends on the processor or processor family.
Assembly language
Assembly language is a low-level programming language that uses short codes called mnemonics to represent machine-code instructions.
A mnemonic is a short, memorable code such as ADD, MOV or SUB. These are easier for a human to understand than raw binary.
Assembly language has a one-to-one correspondence with machine code. This means each assembly-language instruction translates into one machine-code instruction.
Assembly is close to machine code
Assembly language is more readable than machine code, but it still closely matches the processor’s actual instructions.
Assembly language is often used for:
- software for embedded systems
- controlling specific hardware components
- situations where very precise control of the processor is needed
Embedded system
An embedded system is a computer system built into a larger device, usually designed to perform a specific task, such as controlling a washing machine, car braking system or microwave.
A processor cannot directly execute high-level language code or assembly language code.
So:
- high-level language code must be translated or interpreted
- assembly language code must be assembled
- machine code can be executed directly by the processor
Translation rule
If the program is not already in machine code for that processor, it needs a translator before it can be executed.
A translator is software that converts or runs program code so that the processor can carry out the instructions.
The three types you need to know are:
- compiler
- interpreter
- assembler
Compiler
A compiler translates a whole high-level language program into machine code before the program is run.
The output is usually a machine-code program that can be executed later.
- The translated program can run quickly because it is already in machine code.
- The user does not usually need the original source code to run the program.
- The compiler can report errors found during compilation.
- The whole program normally has to be compiled before it can be run.
- If you change the source code, it must be compiled again.
- The compiled machine code is specific to a processor or platform.
Compilers are appropriate when you want to distribute a finished program or when the program needs to run many times efficiently.
Interpreter
An interpreter reads and runs high-level language code statement by statement, without producing a separate machine-code program.
In this GCSE topic, the important detail is that interpreters do not directly generate a machine-code program. Instead, they call suitable machine-code subroutines within the interpreter’s own code to carry out each statement.
- Useful during development because you can test code quickly.
- Errors can be reported as the interpreter reaches them.
- The same source code may run on different systems if each system has a suitable interpreter.
- The program may run more slowly because translation/execution happens as the program runs.
- The user usually needs the interpreter installed.
- The source code may need to be provided.
Interpreters are appropriate for testing, learning programming, scripting and situations where quick development is more important than producing a separate executable file.
Interpreter output
Do not say an interpreter “turns the whole program into machine code”. That describes a compiler. An interpreter runs statements by using machine-code routines inside the interpreter.
Assembler
An assembler translates assembly language into machine code.
Because assembly language has a one-to-one correspondence with machine code, each assembly instruction is assembled into a single machine-code instruction.
Assemblers are appropriate when a programmer has written assembly language, often for embedded systems or for controlling specific hardware.
| Translator | Input | What it does | Output or result | Common use |
|---|
| Compiler | High-level language | Translates the whole program before running | Machine-code program | Finished programs, efficient repeated execution |
| Interpreter | High-level language | Reads and runs statements, calling machine-code routines | No separate machine-code program | Testing, scripting, learning, rapid development |
| Assembler | Assembly language | Translates each assembly instruction | Machine-code program | Embedded systems, hardware control |
Choosing a translator
A programmer has written a finished high-level language program and wants users to run it many times without seeing the source code. Which translator is most suitable?
- The program is written in a high-level language, so the realistic choices are a compiler or an interpreter, not an assembler.
- The program is finished and needs to be run many times, so producing a machine-code program in advance is useful.
- A compiler is most suitable because it translates the whole high-level program into machine code before execution.
Quick translator check
Ask: “What is the input language?” If it is assembly language, use an assembler. If it is high-level language, decide between compiler and interpreter based on whether you want a separate machine-code program or statement-by-statement execution.
Low-level programming can be useful, but it comes with trade-offs.
- Gives direct control over hardware.
- Can be very efficient in terms of speed or memory use.
- Useful for embedded systems and specific hardware components.
- Allows the programmer to use processor-specific features.
- Harder to write and understand.
- More difficult to debug.
- Takes longer to develop.
- Less portable because it is tied to a particular processor or processor family.
- Programmers need detailed knowledge of the hardware.
High-level programming is the normal choice for most software.
- Easier to read, write and maintain.
- Faster development.
- Easier to debug.
- More portable than low-level code.
- Often includes useful libraries and built-in features.
- Must be compiled or interpreted before it can run.
- May give less direct control over hardware.
- May be less efficient than carefully written low-level code in some situations.
Why most programs use high-level languages
Most programs are written in high-level languages because programmer time, readability, maintainability and portability usually matter more than direct hardware control.
In the exam
- If asked to compare high-level and low-level languages, mention both readability for humans and closeness to hardware.
- If asked about machine code, state that it is binary, executed directly by the processor and specific to a processor or processor family.
- If asked to choose a translator, identify the input language first: high-level code uses a compiler or interpreter, while assembly language uses an assembler.
Check yourself
- Why is assembly language classed as low-level even though it is more readable than machine code?
- What is the key difference between a compiler and an interpreter?
- Why might assembly language be chosen for an embedded system?