20 December 2003 Finding memory, part 1 One of the system loader's chores is to find out what memory there is for the system to use, and to pass this information on to the kernel. The system loader has to do it because the services that provide this information are all real-mode BIOS functions. (The system loader runs in real mode; the system itself does not.) There are actually four BIOS services for providing this information, but I'm going to talk about only one of them right now. This service is INT 15h, AX=E801h. I'll talk about this one because it is present on a good percentage of new computers, it returns more accurate information than other services previously available, and it works on my laptop. :) Using this service is very simple: mov ax, 0xE801 int 0x15 The function returns the following:
The distinction between extended and configured memory is apparently that "configured" memory is memory detected the old-fashioned way, through jumpers or switches on the motherboard, and "extended" memory is memory detected the modern way, through chipsets that can detect memory directly. My guess is that the two are usually the same, but if they are different, then the "extended" numbers should be the ones trusted, unless they are zero, in which case the "configured" numbers should be used. So the code that follows the service call might look like this: ; Carry flag set if service doesn't work. jc .error ; Check for extended numbers set to zero. test ax, ax jnz .next_step test bx, bx jnz .next_step ; If extended numbers are zero, ; move configured numbers into AX and BX. mov ax, cx mov bx, dx .next_step: Code I can test this BIOS service simply by storing the returned information into memory and then dumping the memory to the screen. Here's the code: Call the service as above, but this time just store the information to memory (at 0000:1000 — 4KB above the bottom of memory). If the service returns an error, just store all zeroes there. main: mov ax, 0xE801 int 0x15 jnc .1 xor ax, ax xor bx, bx xor cx, cx xor dx, dx .1: mov [0x1000], ax mov [0x1002], bx mov [0x1004], cx mov [0x1006], dx Now dump the memory to the screen. (I care only about the first eight of the sixteen bytes dumped.) xor ax, ax mov fs, ax mov bx, 0x1000 call dump_16 Results My laptop displays the following: 0000:1000: 00 3C 7F 0E 00 3C 7F 0E 00 00 00 00 00 00 00 00 This means that I have 15,360 ("00 3C" or 0x3C00) kilobytes of extended memory between the 1MB and 16MB marks, and 3,711 ("7F 0E" or 0x0E7F) 64-kilobyte blocks between the 16MB and 4GB marks. So first, I have a full fifteen megs of "high memory" below the 16MB mark — I can use memory above and below the 16MB mark as a single contiguous chunk of memory. Second, 3,711 times 64KB is 237,504 kilobytes, which is 231.9375 megabytes. So the BIOS is telling me that I have 246.9375 megabytes of high memory on my laptop. Other pages
• Physical memory: layout, determining RAM size, etc. Check the index for other entries. |