User:Johnburger/Demo/Boot/RAM
Another piece of information needed by the Protected Mode code is just exactly how much RAM the system has - and where. At Boot time, the BIOS knows, so now would be a good time to get it and save it away for future reference.
Of course, as the PC evolved the question "How much memory is there anyway?" got harder and harder to answer, so a number of methods evolved with it. And of course, being implemented by various manufacturers, they each had their own idiosyncrasies...
I use two:
- The first one is the original. It merely gives the top of conventional RAM (less the Extended BIOS Data Area - woohoo! I now have a value for
0009_F???h
in my Memory Map!). - The second is the most up-to-date one. It categorises the different blocks of address space into different types (Reserved, Present, Missing, Faulty etc.)
Having gone to all that effort, however, in the rest of the Demonstrator I ignore the values for the RAM Map returned by the BIOS in the second step above. I'll leave it as an exercise for the reader...
Memory Map
After this code, the Memory Map will look like this:
Address | Usage |
---|---|
0000_0000h
|
Interrupt Vector Table |
0000_0400h
|
BIOS Data Area |
0000_0500h
|
Protected Mode Data |
0000_0518h
|
RAM Map from BIOS |
0000_0800h
|
Moved IDT-to-be |
0000_1000h
|
Loaded Protected Mode code |
0000_2070h
|
Available |
0000_7C00h
|
SS:SP Stack Top
|
0000_7C00h
|
BIOS-loaded Boot Sector |
0000_7E00h
|
Available |
0009_F###h
|
Extended BIOS Data Area |
000A_0000h
|
Adapter / ROM Area |
000B_8000h
|
Text Video Memory |
000F_0000h
|
BIOS ROM |
0010_0000h
|
High Memory *
|
*
Note that this memory is only accessible in Protected Mode - except for the first 64 kiB (less 16 bytes), which you can access with a Segment Register set to 0FFFFh
as long as the A20 Gate is off. By the way: DON'T DO THIS!
Demo/Boot/RAM.inc
; ; Boot/RAM.inc ; ; This module uses the BIOS to determine how much RAM the system has. ; It saves the information away for the system to process after it has entered ; Protected Mode - BIOS functions aren't available then. Boot.RAM: XOR EAX,EAX ; Zero high part of EAX MOV AX,Data.Base >> 4 ; Point to global Data MOV DS,AX MOV ES,AX ; With both Segments INT BIOS.RAMTop.Int ; Get size of Low RAM in kiB SHL EAX,10 ; Turn into number of bytes MOV [Data.RAMTop],EAX ; Top of (Real) RAM XOR EBX,EBX ; Start with beginning of RAM MOV DI,Data.RAMMap ; Store records here .Loop: MOV EAX,BIOS.RAMMap.Fn ; Function call MOV CX,BIOS.RAMMap_size MOV EDX,BIOS.RAMMap.Magic MOV [DI+BIOS.RAMMap.Flags],BYTE BIOS.RAMMap.Flags.DontIgnore INT BIOS.RAMMap.Int ; Call BIOS JC .End ; Carry? Finished CMP EAX,BIOS.RAMMap.Magic ; BIOS function supported? JNE .End ; Nope. CMP CL,BIOS.RAMMap.Flags ; Don't mind optional Flags DWORD JB .Skip ; Ignore if too small JE .Test ; No .Flags entry, so valid TEST [DI+BIOS.RAMMap.Flags],BYTE BIOS.RAMMap.Flags.DontIgnore JZ .Skip ; Ignore if told to .Test: MOV EAX,[DI+BIOS.RAMMap.Length+0] OR EAX,[DI+BIOS.RAMMap.Length+4] JZ .Skip ; Zero-length entry? INC WORD [Data.RAMMap.Num] ; One more Map entry ADD DI,BIOS.RAMMap_size ; Next record CMP DI,Data.Size-BIOS.RAMMap_size ; Any more room? JA .End ; Nope. Leave .Skip: TEST EBX,EBX ; End of sequence? JNZ .Loop ; Not yet... .End: