Classification of Programming Languages
High and low level languages, machine code and assembly language, and the three translators, with a clear account of why anyone would still write low level code today.
High and low level languages
A high level language such as Python, C# or VB.NET is written in a form close to human language, one statement of which usually becomes many machine instructions.
A low level language is close to the hardware. There are two kinds: machine code, which is the binary the processor actually executes, and assembly language, which replaces those binary opcodes with short mnemonics such as ADD, LDA and STA.
| High level | Low level | |
|---|---|---|
| Readability | Close to English, easy to follow | Difficult, one line does very little |
| Portability | Runs on any machine with a translator | Written for one processor family |
| Development speed | Fast, one statement does a lot | Slow, everything is manual |
| Memory management | Handled for you | The programmer's job |
| Control of hardware | Limited and indirect | Complete and direct |
| Efficiency | Good, but the translator decides | Can be optimised precisely |
That single fact explains most of the table. It is why high level code is quicker to write and shorter to read, and why the programmer has less direct control over what the processor actually does.
Why low level languages are still used
Not for ordinary applications. They are used where the extra control is worth the cost:
- Embedded systems with very little memory, where every byte matters,
- Device drivers, which must talk to specific hardware registers directly,
- Small, critical routines inside a larger program, where the last few per cent of speed matters,
- Malware analysis and security work, where you only have the machine code.
- High-level: English-like, portable, one line becomes many instructions.
- Assembly: one short code per instruction, tied to one processor.
- Machine code: binary, the only thing the processor runs.
- The same sum at each level. A translator turns the top into the bottom.
Translators
A processor executes machine code and nothing else, so anything written in another language must be translated. AQA names three translators.
Assembler
An assembler translates assembly language into machine code. The relationship is close to one to one: each mnemonic becomes one machine instruction. That is why assembly is a low level language rather than a high level one.
Compiler
A compiler translates a whole high level program into machine code in one go, producing an executable file.
- Translation happens once, so the finished program runs quickly.
- The program can be distributed without the source code, which protects the developer's work.
- No translator is needed on the machine that runs it.
- All errors are reported together at the end of compilation, which can be daunting.
- The executable only runs on the type of machine it was compiled for.
Interpreter
An interpreter translates and executes a high level program one statement at a time, every time it is run.
- Errors are reported as soon as the offending line is reached, which makes debugging much easier.
- The same source runs on any machine that has the right interpreter.
- Execution is slower, because translation happens every run and every time round a loop.
- The source code has to be given to whoever runs the program.
The most common question is "state one advantage of an interpreter over a compiler". The answer is about development, not about running: errors are reported line by line as they are met, which makes finding a fault far quicker.
- Compiler: translates everything first, then the program runs fast and the source stays private.
- Interpreter: translates and runs one line at a time, so it is easy to test and stops at the first error.
- Assembler: turns assembly into machine code, one line for one instruction.
Key terms you must be able to define
- High level language
- A programming language written close to human language, where one statement becomes many machine instructions.
- Low level language
- A language close to the hardware, either machine code or assembly language.
- Machine code
- The binary instructions a processor executes directly.
- Assembly language
- A low level language using short mnemonics in place of binary opcodes.
- Assembler
- A translator that converts assembly language into machine code.
- Compiler
- A translator that converts a whole high level program into machine code before it is run.
- Interpreter
- A translator that converts and executes a high level program one statement at a time.
- Portability
- The ability of a program to run on different types of computer.
Flashcards
Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.
Reach the top grade on this topic
Two things lift an answer here.
Reasoning from the one to one relationship. Assembly maps almost one instruction to one machine instruction, and a high level statement maps to many. Almost every advantage and disadvantage in the topic follows from that, and saying so is worth more than reciting a list.
Distinguishing development from execution. Interpreters win during development because errors surface immediately. Compilers win at execution because translation has already happened. Answers that keep those two situations apart get full marks; answers that say "interpreters are slower" without saying slower at what do not.
Mistakes that cost marks here
- Saying a compiler is faster than an interpreter without saying at what. Compiling itself is slow, the resulting program is fast.
- Describing assembly language as machine code. Assembly uses mnemonics and still needs assembling.
- Saying an interpreter produces an executable file. It does not: it executes as it translates.
- Claiming low level languages are obsolete. They are used wherever direct hardware control or minimal memory use is essential.
- Forgetting that compiled code only runs on the platform it was compiled for.
The first assembler was written in 1947 by Kathleen Booth, who also designed the assembly language it translated. Every low level language since is a descendant of that idea: give the numbers names a person can read.
Knowledge check
Exam-style questions
Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.
- LA high level language is close to human language and easier to read
- LA low level language is close to the hardware, and one instruction does very little
A high level language is written in a form close to human language, so it is easier to read and one statement performs a substantial amount of work. A low level language is close to the hardware, so each instruction does very little and the code is written for one particular processor.
- LTranslation happens once before the program runs
- LSo the compiled program executes faster than an interpreted one
- LThe program can be distributed as an executable without the source code
- LNo translator is needed on the machine that runs the program
The first advantage is speed of execution. A compiler translates the whole program into machine code once, before it is ever run, so at run time the processor executes machine code directly with no translation happening at all. An interpreter has to translate each line every time it is reached, including every pass round a loop, which is considerably slower. The second advantage is distribution. The compiled executable can be given to users without the source code, which protects the developer's work and means the user does not need a translator installed on their own machine.
- LAn interpreter translates and runs one statement at a time
- LIt stops and reports an error as soon as the line containing it is reached
- LSo the fault is easy to locate and the program can be re-run quickly after a change
An interpreter translates and executes one statement at a time, so when it meets a line it cannot process it stops there and reports the problem. That tells the programmer exactly where the fault is, rather than presenting a list of errors after a full compilation. It also means a small change can be tested immediately by running the program again, with no compilation step in between, which makes the write, test, correct cycle much faster while the program is still being developed.
- LA low level language gives direct control over the hardware
- LLow level code can be made very small and memory efficient
- LLow level code is slow to write and hard to read or maintain
- LA high level language is faster to develop in and easier to maintain
- LBut a high level program is generally larger and gives less direct hardware control
- LReaches a justified conclusion for this specific situation
A low level language has two real advantages here. It gives direct control over the specific hardware in the machine, which matters when the software must operate motors, valves and sensors precisely, and it allows the finished code to be made extremely small, which matters when the memory available is measured in kilobytes. The cost is development. Low level code takes far longer to write, is much harder to read, and is tied to one processor, so moving to a different controller later would mean rewriting rather than recompiling. A high level language reverses all of that: development is quick, the code is readable and maintainable, and it can be recompiled for different hardware, but the compiled program is generally larger and the programmer has less direct control over what the processor does. For a washing machine controller, where memory is severely limited, the hardware is fixed and the program is small and unlikely to change often, the low level route is defensible. In practice most manufacturers take a middle path: write the bulk of the program in a high level language such as C so it stays maintainable, and drop into assembly only for the few routines that must be tightly optimised or must touch the hardware directly.