CD Notes
Complete guide to language processors including compilers, interpreters, assemblers, linkers, loaders, and preprocessors in the compilation system.
Introduction
Language processors are programs that manipulate, translate, or execute programs written in various programming languages. They form the backbone of software development by bridging the gap between human-readable code and machine-executable instructions. Every program you write goes through one or more language processors before it can actually run on a computer.
Types of Language Processors
The major language processors in a computing system are:
| Preprocessor | Compiler | |||
|---|---|---|---|---|
| Interpreter | Assembler | |||
| Linker | Loader |
1. Preprocessor
A preprocessor processes the source program before it reaches the compiler. It handles directives that modify the source code.
Functions:
- Macro expansion: Replaces macro calls with macro definitions
- File inclusion: Inserts contents of header files
- Conditional compilation: Includes/excludes code based on conditions
- Line control: Manages line numbering for error reporting
Example (C Preprocessor):
#include <stdio.h> // File inclusion
#define MAX 100 // Macro definition
#define SQUARE(x) ((x)*(x)) // Function-like macro
#ifdef DEBUG
printf("Debug mode\n"); // Conditional compilation
#endif2. Compiler
A compiler translates a complete high-level language program into an equivalent low-level language program (assembly or machine code).
Characteristics:
- Reads entire source code before translation
- Produces an independent target program
- Reports all errors found during translation
- Can perform optimizations
- The translated program runs faster than interpreted code
Examples:
- GCC (C, C++, Fortran)
- javac (Java to bytecode)
- rustc (Rust)
- clang (C, C++, Objective-C)
3. Interpreter
An interpreter directly executes instructions written in a programming language without producing a compiled target program.
Characteristics:
- Executes code statement by statement
- No separate output file is produced
- Stops at the first error encountered
- Allows interactive programming (REPL)
- Generally slower than compiled programs
Examples:
- CPython (Python)
- Ruby interpreter
- Node.js (JavaScript)
- PHP interpreter
4. Assembler
An assembler translates assembly language programs into machine language (object code). Assembly language uses mnemonics that correspond to machine instructions.
Example:
| MOV AX, 5 | B8 05 00 |
| ADD AX, BX | 01 D8 |
| INT 21h | CD 21 |
Types of Assemblers:
| Type | Passes | Description |
|---|---|---|
| One-pass | 1 | Single scan, limited forward references |
| Two-pass | 2 | First pass builds symbol table, second generates code |
| Multi-pass | >2 | Handles complex macro expansions |
5. Linker
A linker combines multiple object files and library files into a single executable program. It resolves external references between modules.
Functions:
- Symbol resolution: Matches references to definitions across modules
- Relocation: Adjusts addresses to reflect final memory layout
- Library linking: Includes code from static/dynamic libraries
6. Loader
A loader is a system program that places the executable program into main memory and prepares it for execution.
Functions:
- Allocation: Determines memory space for the program
- Loading: Copies the executable into memory
- Relocation: Adjusts addresses based on actual load address
- Linking: Performs dynamic linking if needed
Types:
- Absolute loader: Loads at fixed memory address
- Relocating loader: Can load at any available address
- Dynamic loader: Loads modules on demand at runtime
Complete Language Processing System
The complete flow from source code to execution:
Comparison Table
| Processor | Input | Output | Purpose |
|---|---|---|---|
| Preprocessor | Source with directives | Modified source | Macro expansion, file inclusion |
| Compiler | High-level source | Assembly/object code | Language translation |
| Interpreter | High-level source | Direct execution | Immediate execution |
| Assembler | Assembly language | Machine code | Mnemonic to binary |
| Linker | Object files | Executable | Combine modules |
| Loader | Executable | Program in memory | Prepare for execution |
Interview Questions
- What is the difference between a linker and a loader?
A linker combines multiple object files and resolves external references to produce a single executable. A loader takes the executable, allocates memory, and loads it into main memory for execution.
- Why is a preprocessor needed?
A preprocessor handles directives like macro expansion (#define), file inclusion (#include), and conditional compilation (#ifdef). It simplifies the compiler's job by handling text-level transformations before actual compilation.
- What is the difference between static and dynamic linking?
Static linking includes library code directly in the executable at link time, making it self-contained but larger. Dynamic linking defers library code loading until runtime, producing smaller executables that share library code with other programs.
- Can a language have both a compiler and an interpreter?
Yes. For example, Python has CPython (interpreter) and Cython (compiler). Java has javac (compiler to bytecode) and the JVM (interpreter/JIT). The choice depends on use case requirements.
- What is a cross-compiler?
A cross-compiler runs on one platform (the host) but generates code for a different platform (the target). It's used in embedded systems development where the target device cannot run development tools.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Language Processors.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Compiler Design topic.
Search Terms
compiler-design, compiler design, compiler, design, introduction, language, processors, language processors
Related Compiler Design Topics