I am confused that whether the CPU generates the logical address for a program or does the Compiler do it with the help of CPU? And at what point is this generation performed? Could someone please explain what actually happens?
A logical address is generated by CPU while a program is running.
I found this on several sites and I understand that the CPU fetches this logical address and translates it to physical address with the help of the MMU, but my doubt is how are the logical addresses generated?
I have found many different answers to this question and some say the term "generation" is ill used and others just explain how logical addresses provides virtualization.
A brief explanation about the origin of logical addresses would be highly appreciated, thank you!
The exact details depend on the CPU architecture, compiler, linker, operating system and configuration. The following is therefore a simplification.
Unless in special cases like kernels or when the target system has no MMU, the compiler and linkers deal with logical addresses. Therefore, when saying “address” in the following, I mean “logical address”.
It is rare that a compiler statically knows the address of something. Off the top of my head, I can’t give an example.
When the code refers to some global variable or function, the compiler will create an entry in the relocation table, which is later used by the linker to fill in the address, in a process called relocation. Today, compilers and linkers are usually configured to produce position-independent code, which means that the produced code will work properly independent of the address of the code. If both the referring code and the referred thing can be loaded at a non-fixed address, the compiler cannot put a fixed address in the code.
I won’t go into the details of how position-independent code works, but I will give a simple example. If you have a program containing one function (caller) that calls another (callee), the linker will output code containing the two functions (if we assume that the callee was not inlined into the caller). The code will be loaded in memory contiguously, so the linker knows the difference between the call instruction and the beginning of the callee. In this case, the call instruction could refer to the callee by using an address relative to the program counter. When the CPU executes the call instruction, it adds the current program counter and the difference between the call instruction and the beginning of the callee to generate the address of the callee.
A variable stored on the stack is usually referred to by an address relative to the stack pointer. A dynamically allocated object has its address generated by the dynamic memory allocator.
To summarize, the address generation works through the interaction of compiler, linker and CPU. Only in rare cases, the compiler can generate the address alone. Because position-independent code is the standard nowadays, the linker will usually not generate the address, either. The address is usually generated by the CPU at run-time, but based on information from the compiler and the linker.