爲何0x00400000是可執行文件的默認基址?EXE base address start with 400000H,Why is 0x00400000 the default base addr

DLL的默認基址是0x10000000,但EXE的默認基址是0x00400000。爲何EXE特別值?兆字節
什麼特別之處它與x86上單頁目錄條目映射的地址空間量和1987年
設計決策有關。對EXE基地址的惟一技術要求是它是一個64KB的倍數但基地址的一些選擇比其餘選擇更好。
選擇基址的目的是最小化模塊必須從新定位的可能性。這意味着不會與地址空間中已有的東西發生衝突(這將迫使您從新定位),也不會與稍後可能到達地址空間的東西發生衝突(迫使他們從新定位)。對於可執行文件,不會與稍後可能到達的內容發生衝突部分意味着避免地址空間的區域每每填充DLL。因爲操做系統自己將DLL置於高地址而且非操做系統DLL的默認基址爲0x10000000,這意味着可執行文件的基址應該低於0x10000000,而且越低,您擁有的空間越大在開始與DLL衝突以前。可是你能走多遠?
第一部分意味着你也想避免已經存在的東西。Windows NT在低地址時沒有不少東西。惟一已經存在的是一個PAGE_NOACCESS映射爲零頁面,以便捕獲空指針訪問。所以,在Windows NT上,您能夠將可執行文件基於0x00010000,而且許多應用程序都是這樣作的。
可是在Windows 95上,已經存在不少東西。Windows 95虛擬機管理器將第一個64 KB的物理內存永久映射到第一個64 KB的虛擬內存,以免CPU錯誤。(Windows 95 必須解決許多CPU錯誤固件錯誤。)此外,整個第一兆字節的虛擬地址空間映射到活動虛擬機的邏輯地址空間。(Nitpickers:實際上略高於一兆字節。)x86處理器的virtual-8086模式須要這種映射行爲。
Windows 95與其前身Windows 3.1同樣,在一個特殊的虛擬機(稱爲系統虛擬機)中運行Windows,爲了兼容性,它仍然經過16位代碼路由各類各樣的東西,以確保誘餌以正確的方式嘎嘎做響所以,即便CPU正在運行Windows應用程序(而不是基於MS-DOS的應用程序),它仍然保持虛擬機映射處於活動狀態,所以它沒必要進行頁面重映射(以及來自昂貴的TLB刷新)與它)每一次它須要去到MS-DOS兼容層。
好的,因此第一兆字節的地址空間已經不在了。那另外三兆呢?
如今咱們回到文章頂部的那個小提示。
爲了快速進行上下文切換,Windows 3.1虛擬機管理器將每一個VM上下文「舍入」到4 MB這樣作能夠經過簡單地更新頁面目錄中的單個32位值來執行內存上下文切換。(Nitpickers:你還必須標記實例數據頁面,但這只是翻了十幾個位。)這種舍入致使咱們失去3兆字節的地址空間,但考慮到有4千兆字節的地址空間,損失少了超過十分之一的百分比被認爲是顯着的績效改善的公平權衡。(特別是由於當時沒有任何應用程序接近開始劃破這個限制的表面。你的整個計算機首先只有2MB的RAM!)
此內存映射已轉移到Windows 95中,並進行了一些調整以處理32位Windows應用程序的單獨地址空間所以,可執行文件能夠在Windows 95上加載的最低地址是4MB,即0x00400000。
極客雜事:爲防止Win32應用程序訪問MS-DOS兼容性區域,平面數據選擇器其實是一個向下擴展選擇器,它停在4MB邊界。(相似地,16位Windows應用程序中的空指針會致使訪問衝突,由於空選擇器無效。它不會訪問中斷向量表。)
連接器選擇0x0400000可執行文件的默認基址,以便生成的二進制文件能夠在Windows NT和Windows 95上無需重定位加載。沒有人真正關心Windows 95的目標,因此原則上,連接器人員能夠選擇不一樣的如今是默認基地址。但除了使圖表看起來更漂亮以外,沒有真正的動機去作,特別是由於ASLR不管如何都讓整個問題都沒有實際意義。此外,若是他們改變它,那麼人們會問,「爲何一些可執行文件的基地址爲0x04000000,一些可執行文件的基地址爲0x00010000?」html

TL; DR:快速進行上下文切換。app

The default base address for a DLL is 0x10000000, but the default base address for an EXE is 0x00400000. Why that particular value for EXEs? What’s so special about 4 megabytes
It has to do with the amount of address space mapped by a single page directory entry on an x86 and a design decision made in 1987.
The only technical requirement for the base address of an EXE is that it be a multiple of 64KB. But some choices for base address are better than others.
The goal in choosing a base address is to minimize the likelihood that modules will have to be relocated. This means not colliding with things already in the address space (which will force you to relocate) as well as not colliding with things that may arrive in the address space later (forcing themto relocate). For an executable, the not colliding with things that may arrive later part means avoiding the region of the address space that tends to fill with DLLs. Since the operating system itself puts DLLs at high addresses and the default base address for non-operating system DLLs is 0x10000000, this means that the base address for the executable should be somewhere below 0x10000000, and the lower you go, the more room you have before you start colliding with DLLs. But how low can you go?
The first part means that you also want to avoid the things that are already there. Windows NT didn’t have a lot of stuff at low addresses. The only thing that was already there was a PAGE_NOACCESS page mapped at zero in order to catch null pointer accesses. Therefore, on Windows NT, you could base your executable at 0x00010000, and many applications did just that.
But on Windows 95, there was a lot of stuff already there. The Windows 95 virtual machine manager permanently maps the first 64KB of physical memory to the first 64KB of virtual memory in order to avoid a CPU erratum. (Windows 95 had to work around a lot of CPU bugs and firmware bugs.) Furthermore, the entire first megabyte of virtual address space is mapped to the logical address space of the active virtual machine. (Nitpickers: actually a little more than a megabyte.) This mapping behavior is required by the x86 processor’s virtual-8086 mode.
Windows 95, like its predecessor Windows 3.1, runs Windows in a special virtual machine (known as the System VM), and for compatibility it still routes all sorts of things through 16-bit code just to make sure the decoy quacks the right way. Therefore, even when the CPU is running a Windows application (as opposed to an MS-DOS-based application), it still keeps the virtual machine mapping active so it doesn’t have to do page remapping (and the expensive TLB flush that comes with it) every time it needs to go to the MS-DOS compatibility layer.
Okay, so the first megabyte of address space is already off the table. What about the other three megabytes?
Now we come back to that little hint at the top of the article.
In order to make context switching fast, the Windows 3.1 virtual machine manager 「rounds up」 the per-VM context to 4MB. It does this so that a memory context switch can be performed by simply updating a single 32-bit value in the page directory. (Nitpickers: You also have to mark instance datapages, but that’s just flipping a dozen or so bits.) This rounding causes us to lose three megabytes of address space, but given that there was four gigabytes of address space, a loss of less than one tenth of one percent was deemed a fair trade-off for the significant performance improvement. (Especially since no applications at the time came anywhere near beginning to scratch the surface of this limit. Your entire computer had only 2MB of RAM in the first place!)
This memory map was carried forward into Windows 95, with some tweaks to handle separate address spaces for 32-bit Windows applications. Therefore, the lowest address an executable could be loaded on Windows 95 was at 4MB, which is 0x00400000.
Geek trivia: To prevent Win32 applications from accessing the MS-DOS compatibility area, the flat data selector was actually an expand-down selector which stopped at the 4MB boundary. (Similarly, a null pointer in a 16-bit Windows application would result in an access violation because the null selector is invalid. It would not have accessed the interrupt vector table.)
The linker chooses a default base address for executables of 0x0400000 so that the resulting binary can load without relocation on both Windows NT and Windows 95. Nobody really cares much about targeting Windows 95 any more, so in principle, the linker folks could choose a different default base address now. But there’s no real incentive for doing it aside from making diagrams look prettier, especially since ASLR makes the whole issue moot anyway. And besides, if they changed it, then people would be asking, 「How come some executables have a base address of 0x04000000 and some executables have a base address of 0x00010000?」less

TL;DR: To make context switching fast.ide

相關文章
相關標籤/搜索