The process is relatively simple to explain, but not so to carry out .
The first thing: CPUs have a series of requirements to be able to execute any piece of code: certain registers have to point to valid memory addresses.
Additionally, the rules imposed by the Operating System of turn must be complied with: a certain piece of memory can only be accessed by a certain program, and in a certain way (reading, writing, execution).
The basic process of execution (which does not load) consists of preparing the memory and the registers of the CPU so that they fulfill the imposed requirements. This is carried out by the Operating System .
For the above, certain data of the file to be executed is consulted.
Once the memory is prepared, the code is loaded, each portion in the necessary part. The segments of program data are loaded into the dedicated memory area for data, the segments of executable code in the code area, ...
Here, the load can be misleading. Through the process of mapping files in memory , the above load can be postponed until the CPU does not really need to access strong> to the memory area in question.
Once the code loaded , we proceed to its dynamic link . That is, the segment is consulted from the file that contains the name of the .dll
libraries that are needed. Some will already be loaded (in shared memory zones, with execution for everyone). Others do not, and it will be necessary to repeat the load process for them (with their peculiarities, for example, the libraries do not need a stack ( stack ).
Finally, it's all loaded (or * mapped in memory). Now, you have to overwrite the code points of the program in which certain imported functions are called, by the actual addresses of the same.
This is also deceptive . There are mechanisms to not have to go through all the memory , using some memory zones like intermediate tables . The final result, however, is the same: all calls to .dll
point to the desired code.
Now, yes, you can start the execution of the program, forcing the CPU to create a new process, and using the memory areas that so mimo have been prepared.
Normally, the execution itself does not pass directly to the function WinMain
, or main
, or whatever. It is called first a piece of code placed by the compiler, which is responsible for performing initialization tasks of the data. In C ++, for example, it is this pre-main code that is responsible for calling the static instance constructors.
Now yes; finally, we call our WinMain( )
.
One of the things we can do within WinMain( )
is register our window function , which will be used by Windows to deliver the messages. These messages are generated independently of us , most of them are artificial (generated by the system itself). But that is another issue, and it will be told on another occasion ...