Why does a general program usually start with 0x8000?

I'm not new to the bootloader and system SW, but I do not know the origin of the reason why the general program starts with 0x8000 . I already know that the address 0x8000 used as the starting address in a regular C / C ++ program.

Does the minimum bootloader size for a common program up to 0x8000 ? Or the minimum ROM block size to be assigned to a 32KB bootloader? Or is there another reason?

I would like to know about this, historically or logically, and in terms of a virtual address.




I appreciate everything, your time and help with this. To make the question more understandable, the question is connected with a virtual address not with a physical one.

I basically agree with R's point of view in terms of physical memory.

Not to mention a specific different system, for example linux (even in android), general RTOS (the kernel and others, especially the ARM linker), they all use the 0x8000 address as a common starting address program. such as crt_begin.o, crt.o etc. located at 0x0 with the bootloader exist in this area.

Therefore, I assume that the minimum bootloader size for the general program is 32 KB, taking into account the block size, if it is in BootROM at boot time (cold boot).

Ummm, But I'm not sure ...

+43
c ++ c linker bootloader
Mar 13 '12 at 6:32
source share
5 answers

In general, on all but the smallest embedded systems, the developer of the ABI platform wants to avoid using the lowest addresses so that you can avoid capturing null pointers. Having multiple KBs of non-exclusive addresses gives you extra security if the null pointer is dereferenced by an offset of an array or structure, as in null_ptr->some_member .

+19
Mar 13 2018-12-12T00:
source share

It depends on the system, and programs start from different addresses on different systems. On Unix, it is normal (or perhaps even required by Posix) to use address 0 as a null pointer and not display the first page of virtual memory, so dereferencing a null pointer will violate the segment. I suspect that other systems using address 0 as a null pointer behave similarly (but how much they reserve may vary). (Historically, the first was usually displayed only and filled with zeros, make the null pointer behave as if it were an empty string, a pointer to "" . "" It's about 25 years old, however.)

I would expect that even today some embedded systems load a program starting at address 0.

+6
Mar 13 2018-12-12T00:
source share

This is somewhat arbitrary, but on linux, at least the linker solves it. The general idea is to reserve some space to throw null pointer exceptions. To help avoid marking up the kernel NULL space when executing arbitrary user code in kernel mode, linux does not allow the bottom of the memory to be displayed. /proc/sys/vm/mmap_min_addr controls the lowest address you can map (you can change it to 0 and map the page to 0 if you want).

On linux, you can look at the memory mapping by looking at /proc . For example,

  genwitt ~> cat / proc / self / maps 
 00400000-0040c000 r-xp 00000000 08:01 354804 / bin / cat
 0060b000-0060c000 r - p 0000b000 08:01 354804 / bin / cat
 0060c000-0060d000 rw-p 0000c000 08:01 354804 / bin / cat
 01dda000-01dfb000 rw-p 00000000 00:00 0 [heap]
 7f5b25913000-7f5b25a97000 r-xp 00000000 08:01 435953 /lib64/libc-2.14.1.so
 7f5b25a97000-7f5b25c97000 --- p 00184000 08:01 435953 /lib64/libc-2.14.1.so
 7f5b25c97000-7f5b25c9b000 r - p 00184000 08:01 435953 /lib64/libc-2.14.1.so
 7f5b25c9b000-7f5b25c9c000 rw-p 00188000 08:01 435953 /lib64/libc-2.14.1.so
 7f5b25c9c000-7f5b25ca1000 rw-p 00000000 00:00 0 
 7f5b25ca1000-7f5b25cc2000 r-xp 00000000 08:01 436061 /lib64/ld-2.14.1.so
 7f5b25cd2000-7f5b25e97000 r - p 00000000 08:01 126248 / usr / lib64 / locale / locale-archive
 7f5b25e97000-7f5b25e9a000 rw-p 00000000 00:00 0 
 7f5b25ec0000-7f5b25ec1000 rw-p 00000000 00:00 0 
 7f5b25ec1000-7f5b25ec2000 r - p 00020000 08:01 436061 /lib64/ld-2.14.1.so
 7f5b25ec2000-7f5b25ec3000 rw-p 00021000 08:01 436061 /lib64/ld-2.14.1.so
 7f5b25ec3000-7f5b25ec4000 rw-p 00000000 00:00 0 
 7fff18c37000-7fff18c58000 rw-p 00000000 00:00 0 [stack]
 7fff18d0c000-7fff18d0d000 r-xp 00000000 00:00 0 [vdso]
 ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] 
+3
May 30 '12 at 16:16
source share

I would suspect in many cases that the first 32K were reserved for using the code / mode of operation of monitors. In many 8051 boards, eval wasnโ€™t so unusual that the default was 0x1000 or 0x2000 for all applications depending on the resident monitor (some of them also worked as debuggers).

32K may be your u-boot / etc download site.

+2
May 30 '12 at 14:01
source share

I believe the answer is more about handling interrupts. The interrupt handler addresses are set at the hardware level. In Intel 8086, a direct translation table was specified on the interrupt handler code and the corresponding interrupt handling procedure. This was probably done using a combinatorial scheme and, therefore, in order to maintain direct compatibility, it would be wiser to place them at the start of the memory, and not at the end, to prevent changes every time. Thus, the starting address of execution will be on the other end of the memory. In addition, it was necessary that this block contained enough code to load the memory segment program and a jump command to switch to execute code from this code address.

+2
May 30 '12 at 16:27
source share



All Articles