1. Introduction
In this tutorial, we’ll cover address binding in operating systems (OS).
2. Why Do We Need Address Binding?
In brief, address binding means mapping computer instructions and data to locations in RAM.
High-level programs are loaded into the memory for their execution in the CPU. The CPU transforms programs into processes and generates logical addresses to communicate with the main memory.
Logical addresses are internal references in the virtual address space of a process. Processes know only the logical address, whereas they need to access physical memory to fetch the instructions and data. Physical addresses index the locations in the main memory.
The Memory Management Unit (MMU) translates logical addresses into physical (RAM) addresses. Mapping a logical address to a physical address is called address binding or address mapping.
3. The Context of Address Binding
In a source code, we have symbolic addresses. They are the identifiers of the variables, functions, classes, and other constructs.
The assembler maps them to relative numerical addresses. Relative addresses show the offset to the starting point of the memory that the code will take. However, the initial address isn’t determined in this phase. The assembler outputs object files and gives them to the linker.
The linker takes object files and other pieces of code to generate an executable file. First, it searches for all the libraries needed to execute the object file and appends them to it one after another. After that, it establishes links correctly so the modules can reference each other.
Finally, the output is passed to the loader. Specifically, the loader allocates memory for the executable code and loads it:
After that, we can execute our code.
4. Types of Address Binding
There are three mechanisms for address binding depending on whether we do it at the compile time, load time, or execution time.
4.1. Compile-Time Binding
The compiler can do the compile-time binding during compilation. In this type of binding, it translates the symbolic addresses into absolute addresses.
An absolute address is an address expression with a fixed value that doesn’t depend on run-time considerations. For instance, its location in the memory remains the same throughout program execution.
If we know where the program will reside in memory at the compile time, we can generate an absolute (static) code before loading the program.
So, this is possible only if we know, before loading and execution, how much memory to use. If that’s the case, we can infer from where to start allocating memory for our program and prepare everything in advance. However, that’s rarely possible. An example of a system with compile-time address binding is MS-DOS.
4.2. Load-Time Binding
The load-time address binding takes place during the loading of a program into the memory. The operating system memory manager (loader) is the element in charge.
Here, the compiler doesn’t do binding but translates symbolic addresses from the source code to relative addresses.
The loader then translates relative addresses to absolute addresses. It needs to know the base address in the main memory from which to start the allocation. Therefore, when loading a program, we compute the physical addresses by adding them to the base address:
In the image above, the relative address 250 becomes the absolute address 142500 because the base is 14000.
4.3. Execution-Time Binding
If the program is compiled, all the variables are known in advance. However, the memory requirements may not be if, for example, we load some data from a file dynamically, and we can’t determine how much space we need for the data before we read the file. Similarly, if the program is interpreted, not all variables can be considered before execution.
Execution-time binding covers these cases. Addresses and memory are reserved dynamically, i.e., when we need to do that during execution.
The majority of general-purpose OSs can use this mechanism. Some popular OSs like Windows and Linux practically implement dynamic loading, dynamic linking, and dynamic address binding.
5. Memory Protection
Address binding enables memory protection. For example, in a multi-programming environment, processes are executed simultaneously and concurrently access the memory and the CPU.
By performing address binding, the OS guarantees the protection of each process’s memory space. A RAM address can be accessed only by the process whose address space it belongs to. For instance:
No process can access another one’s memory space because address binding ensures memory protection.
6. Conclusion
In this article, we presented address binding in operating systems. It can happen at different steps during a program’s execution.
Address binding protects memory by preventing processes from accessing the memory locations of other processes.