Having stumbled upon this question (and answer): https://stackoverflow.com/questions/2170843/va-virtual-adress-rva-relative-virtual-address on my quest for understanding Windows' PE format, I'm wondering: why is the default imagebase value 0x400000? Why couldn't we just start at 0? A VA would then be, in all practical purposes, equal to an RVA.

I'm clearly missing something, but I've been unable to find a reasonable explanation of this for the last 40 minutes.

  • well, zero would be the bios area... so thats a no go... stack and heap can start at around 0x10000 and some other dlls etc are down there (.nls files and so on) open up an exe in ollydbg, then look at the memory view, you'll see whats down there, typically its some system stuff, at least one nls file on my system and the start of the stack of the main thread and higher than 0x80000000 (on 32 bit anyway) is for mem mapped files, drivers and such
    – evlncrn8
    Sep 15, 2014 at 18:44
  • 1
    @evlcrn8 Hold on - the OS translates all memory references to physical locations anyway, so by no means can I access BIOS stuff or pretty much anything that doesn't belong to me... isn't it so?
    – user4520
    Sep 15, 2014 at 18:45
  • 3
    @evlcrn8: By default, memory at 0x00000000 is unmapped; it most certainly is not "the bios area". And files mapped into memory from user-mode are mapped below 0x80000000. Sep 15, 2014 at 18:49
  • i just remember it as the bios area from the old dos days, and it kinda stuck with me, im pretty sure files mapped via mapviewoffile were at the > 0x80000000 when i tested though
    – evlncrn8
    Sep 15, 2014 at 19:18
  • Address 0 is usually reserved by the OS because it makes it easier to debug null dereference bugs (by crashing). I would not be surprised if parts of the DOS support uses address 0 but that does not matter to normal Windows processes.
    – Anders
    Mar 1, 2022 at 1:42

2 Answers 2


why is the default imagebase value 0x400000?

From Peering Inside the PE: A Tour of the Win32 Portable Executable File Format:

In executables produced for Windows NT, the default image base is 0x10000. For DLLs, the default is 0x400000. In Windows 95, the address 0x10000 can't be used to load 32-bit EXEs because it lies within a linear address region shared by all processes. Because of this, Microsoft has changed the default base address for Win32 executables to 0x400000.

Note that the default (or "preferred") base address is set by the linker (GCC's ld, Microsoft VC++'s link.exe, etc.) at build-time; the default (or "preferred") base address is not determined by Windows.

  • the microsoft one is a bit odd, last time i looked it works from the name of the module, and calculates the base from that
    – evlncrn8
    Sep 15, 2014 at 19:16
  • 1
    @evlncrn8: According to msdn.microsoft.com/en-us/library/f7f5138s.aspx, even the latest MS VC++ link.exe uses 0x400000 as the default base address. Sep 15, 2014 at 20:00
  • @evlncrn8: you might be seeing "load address randomization".
    – JDługosz
    Sep 15, 2014 at 22:08
  • 5
    Raymond Chen posted a detailed writup on this exact question: blogs.msdn.com/b/oldnewthing/archive/2014/10/03/10562176.aspx
    – QAZ
    Oct 3, 2014 at 14:23
  • 2
    @QAZ: Wow, he posted that this morning. Maybe this StackExchange question prompted Raymond to write that blog post :) I'd say that the explanation given in that new blog post is more complete than the one to which I linked above, so feel free to post it as an answer here (so you get credit) and I'll be happy to vote it up. Oct 3, 2014 at 14:38

you can alter the base if you so wish msvc compile drivers with an image base of 0x10000

:\>kd -c "!dh acpi;q" -z c:\WINDOWS\system32\drivers\acpi.sys | grep -i image
00010000 image base
    5.01 image version
   2DD80 size of image


here is how to alter usermode executables imagebase base must be multiples of 64k if base:0 is used exe will be having an image base of 0x10000

:\>dir /b & type * & cl /nologo /Zi * /link /base:0x200000 & dir /b


#include <stdio.h>
#include <stdlib.h>
int main (void)
    printf("all the bases belongs to base\n");

all the bases belongs to base

:\>cdb -c "q;" sysbp.exe | grep -i modload
ModLoad: 00200000 00222000   sysbp.exe
ModLoad: 7c900000 7c9b2000   ntdll.dll
ModLoad: 7c800000 7c8f6000   C:\WINDOWS\system32\kernel32.dll


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.