📜 ⬆️ ⬇️

Why 0x00400000 is the default base address for exe

The default base address for a DLL is 0x10000000 , but for executable files it is 0x00400000. Why exactly such a special value for exe? What's so special about 4 megabytes ?

This is related to the size of the address space displayed by a single page table in the x86 architecture, and this design was chosen in 1987.

The only technical requirement for the base address of the EXE is a multiplicity of 64 KB . But some base address options are better than others.
')
The goal of choosing a base address is to minimize the likelihood that modules will be moved. This means that it is necessary to prevent collisions with 1) other objects that are already in the address space (which will cause movement); 2) as well as with objects that may appear in the address space later (forcing them to move). For executable files, avoiding conflicts with objects that may appear later means leaving the area of ​​the address space, which can be filled with DLLs. Since the operating system itself places the DLL files in the upper addresses and the default base address for non-system DLLs is 0x10000000, the base address for the EXE must be somewhere younger than 0x10000000, and the younger, the more space will remain before you start to conflict with libraries. But how low should you go?

Item 1 means that you also need to avoid objects that are already in memory. In Windows NT, there wasn’t that much at lower addresses. The only thing that was there was the PAGE_NOACCESS page, which occupied the zero address in order to catch attempts to access the null pointer. Therefore, in Windows NT, you can place executable files at the base address 0x00010000, and many applications did just that.

But in Windows 95, the lowest addresses were loaded much more. The Windows 95 virtual machine manager constantly displayed the first 64KB of physical memory into the first 64KB of virtual memory to avoid CPU errors. (Windows 95 had to bypass many CPU bugs and firmware bugs ). Moreover, the entire first megabyte of the virtual address space was displayed in the logical address space of the active virtual machine. (For pedants: in reality, a little more than a megabyte ). This mapping method was a requirement of the virtual-8086 x86 processors.

Windows 95, like its predecessor, Windows 3.1, ran Windows in a special virtual machine (known as System VM), and, for compatibility, still ran a variety of things through 16-bit code, just to make sure the duck quacks correctly . Therefore, even when the CPU was processing a Windows application (and not an MS-DOS application), the virtual machine’s address space was saved, so you didn’t have to re-do it (and at the same time a resource-intensive buffer address conversion procedure ) every time you need to run compatibility mode with MS-DOS.

So, the first megabyte of address space is leaving the scene. What about the other three megabytes?

Now we return to the little hint at the beginning of the article.

To quickly switch context, the Windows 3.1 virtual machine manager “rounded” the context of each virtual machine to 4 MB. It did so that the context could be switched by updating one 32-bit value in the page table. (For pedants: you need to handle attribute pages , but this is only a dozen or so bits). Due to rounding, we lose three megabytes of address space, but since we have 4 gigabytes of address space, a loss of less than 0.1% seemed like a small sacrifice for a significant performance improvement. (Moreover, at that time no application came close to this limit. In general, the computer had only 2 MB of physical memory).

The memory mapping method was transferred to Windows 95, with some corrections for working with separate address spaces of 32-bit Windows applications . As a result, the lowest address where the executable file can be downloaded to Windows 95 was 4 MB, that is, 0x00400000.

Little things for geeks. To prevent Win32 applications from accessing the storage space that is used for MS-DOS compatibility mode , the simple data selector was in fact an expandable down selector that stopped at the 4 MB border. (Similarly, a null pointer in a 16-bit Windows application resulted in an access violation, because the null selector was invalid).

The linker chooses the default base address for executable files 0x0400000, so the EXE can be loaded without moving on both Windows NT and Windows 95. No one really cares about optimization under Windows 95, so now, in principle, the link builders might choose a different base address as default. But there is no special incentive to do this, apart from the aesthetic pleasure from harmony in the diagram, especially since ASLR still questions this harmony. And besides, if they change the base address, then people will begin to ask: “Why is the base address 0x04000000 for some executables, and 0x00010000 for others?”.

TL; DR: For fast context switching.

Source: https://habr.com/ru/post/240843/


All Articles