Table of contents
1.
Introduction
2.
Cousins of Compiler
2.1.
Preprocessor
2.1.1.
Macro processing 
2.1.2.
Rational Preprocessors
2.1.3.
File Inclusion
2.1.4.
Language extension
2.1.5.
Error Detection
2.1.6.
Conditional Compilation
2.2.
Assembler
2.3.
Linker
2.4.
Loader
3.
Frequently Asked Questions
3.1.
Why do we need a compiler?
3.2.
What is the difference between a preprocessor and a compiler?
3.3.
What is the difference between an assembler and a compiler?
4.
Conclusion
Last Updated: Mar 27, 2024

Cousins of Compiler

Author Gaurav Gandhi
2 upvotes
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Hello Ninjas, We hope you have encountered the term compiler in your programming journey. You can think of a compiler as a translator who translates a high-level language into a low-level language without making any changes in the meaning of the program so that it can be understood by computers.

Cousins of a compiler consist of a preprocessor, an assembler, and a loader and linker, which play an essential role in converting a high-level language into a low-level language along with the Compiler. 

Don't worry if you haven't heard about them before because, in this article, we will learn about them in detail.

So without any delays, let's dive deep into the topic. 

Cousins of Compiler

Cousins of Compiler

Converting a high-level language into a low-level language takes multiple steps and involves many programs apart from the Compiler. Before the compilation can start, our source code needs to be preprocessed. After the compilation, our code needs to be converted into executable code to execute on our machine. These essential tasks are performed by the preprocessor, assembler, Linker, and Loader. They are known as the Cousins of the Compiler. Let's study them in detail.

 

Processing steps

 


Let's see who the cousins of Compiler are and what their contributions are in the process of converting a high-level language into a low-level language.

Preprocessor

The preprocessor is one of the cousins of the Compiler. It is a program that performs preprocessing. It performs processing on the given data and produces an output. The output generated is used as an input for some other program.

The preprocessor increases the readability of the code by replacing a complex expression with a simpler one by using a macro.

A preprocessor performs multiple types of functionality and operations on the data.

Some of them are-

Macro processing 

Macro processing is mapping the input to output data based on a certain set of rules and defined processes. These rules are known as macros. 

Rational Preprocessors

Relational preprocessors are the processors that change older languages with some modern flow-of-control and data-structuring facilities.

File Inclusion

The preprocessor is also used to include header files in the program text. A header file is a text file included in our source program file during compilation. When the preprocessor finds an #include directive in the program, it replaces it with the entire content of the specified header file.

Language extension

Language extension is used to add new capabilities to the existing language. This is done by including certain libraries in our program, which provides extra functionality. An example of this is Equel, a database query language embedded in C.

Error Detection

Some preprocessors are capable of performing error-checking on the source code that is given as input to them. For example, it can check if the headers files are included properly and if the macros are defined correctly or not.

Conditional Compilation

Certain preprocessors are capable of including or excluding certain pieces of code based on the result of a condition. They provide more flexibility to the programmers for writing the code as they allow the programmers to include or exclude certain features of the program based upon some condition.  

Assembler

Assembler is also one of the cousins of the compiler. A compiler takes the preprocessed code and then converts it into assembly code. This assembly code is given as input to the assembler, and the assembler converts it into the machine code. Assembler comes into effect in the compilation process after the Compiler has finished its job.

There are two types of assemblers-

  • One-Pass assembler:  They go through the source code (output of Compiler) only once and assume that all symbols will be defined before any instruction that references them.

 

  • Two-Pass assembler: Two-pass assemblers work by creating a symbol table with the symbols and their values in the first pass, and then using the symbol table in a second pass, they generate code.

Linker

Linker takes the output produced by the assembler as input and combines them to create an executable file. It merges two or more object files that might be created by different assemblers and creates a link between them. It also appends all the libraries that will be required for the execution of the file. A linker's primary function is to search and find referred modules in a program and establish the memory address where these codes will be loaded.

Multiple tasks that can be performed by linkers include-

  • Library Management: Linkers can be used to add external libraries to our code to add additional functionalities. By adding those libraries, our code can now use the functions defined in those libraries.
     
  • Code Optimization: Linkers are also used to optimize the code generated by the compiler by reducing the code size and increasing the program's performance.
     
  • Memory Management: Linkers are also responsible for managing the memory requirement of the executable code. It allocates the memory to the variables used in the program and ensures they have a consistent memory location when the code is executed.

 

  • Symbol Resolution:  Linkers link multiple object files, and a symbol can be redefined in multiple files, giving rise to a conflict. The linker resolves these conflicts by choosing one definition to use.

Loader

The loader works after the linker has performed its task and created the executable code. It takes the input of executable files generated from the linker, loads it to the main memory, and prepares this loaded code for execution by a computer. It also allocates memory space to the program. The loader is also responsible for the execution of programs by allocating RAM to the program and initializing specific registers.

 

Following tasks are performed by the loader

  • Loading: The loader loads the executable files in the memory and provides memory for executing the program.

 

  • Relocation: The loader adjusts the memory addresses of the program to relocate its location in memory.

 

  • Symbol Resolution: The loader is used to resolve the symbols not defined directly in the program. They do this by looking for the definition of that symbol in a library linked to the executable file.
     
  • Dynamic Linking: The loader dynamically links the libraries into the executable file at runtime to add additional functionality to our program. 


Also see, Cross Compiler

Frequently Asked Questions

Why do we need a compiler?

Programs that are written by the programmers are in a high-level language, which is not understood by the compiler. A compiler is a computer software program that converts the source code written in one computer language (the high-level language) into another computer language (the low-level language) without changing the meaning of the code so that the machine can understand it.

What is the difference between a preprocessor and a compiler?

A preprocessor performs preprocessing on the source code before sending it as input to the compiler. It converts the source code into the preprocessed code. In comparison, the compiler converts the preprocessed source code into the target language. It takes the output of the preprocessor as an input.

What is the difference between an assembler and a compiler?

A compiler converts the preprocessed code to an assembly code while an assembler takes the output of the Compiler, i.e., the assembly code, and converts it into the machine code. The output of a compiler is the "Mnemonic" form of a machine code, while the output of an assembler is binary code.

Conclusion

Congrats, Ninja!! You've learned what cousins of compiler mean and their importance in converting high-level language to low-level language. You've also learned the different steps in converting high-level language into low-level language.

We have also added some FAQs related to the cousins of the Compiler. 

Recommended Reading-

Thanks for reading this article. I hope you would have found the blog insightful and understood who the cousins of compiler are, and please upvote if you liked the article.

Also, check out some of the Guided Paths on topics such as Data Structure and AlgorithmsCompetitive ProgrammingOperating SystemsComputer Networks, DBMSand  System Design, etc. as well as some Contests, Test SeriesInterview Bundles, and some Interview Experiences curated by top Industry Experts only on Coding Ninjas Studio.

Happy Learning!!

 

Live masterclass