简体   繁体   中英

Finding Memory Size in Boot without DOS, Windows, Linux

I am writing a simple program in Assembly (NASM). When the boot sector loads it has to display all the memory (RAM) installed in the computer in Megabytes. There would be no Operating System (DOS, Windows, Linux) when the boot sector is loaded, so how would I find out total RAM size. I have 2 GB RAM in my computer. I have searched alot on the internet but could not find a solution.

Is there an interrupt of BIOS that shows memory size of 2 GB? There is an interrupt that was used in old computers to shows memory, but it does not shows all 2 GBs. I checked and there is no solution for this in Ralph Brown List. May be someone knows alot more about BIOS. If BIOS does not provide this facility then can I use C/C++ to find out Total RAM size? And call C/C++ code from assembly? What function of C/C++ would be used to find Total RAM size?

Remember that my assembly code will do a cold boot and there would be no operating system to provide any facility to my code.

EDITED:

I read the website http://wiki.osdev.org/Detecting_Memory_%28x86%29 . And decided to check if int 15 works. So I got the code from this website and edited it to test if int 15 EAX = E820 works. But it fails to work and the output is 'F' in .failed1. 'F' is test case which I made to check for "unsupported function". Test Cases are 'F', 'G' and 'H'. Here is the code.

; use the INT 0x15, eax= 0xE820 BIOS function to get a memory map
; inputs: es:di -> destination buffer for 24 byte entries
; outputs: bp = entry count, trashes all registers except esi
do_e820:

   xor ebx, ebx     ; ebx must be 0 to start
   xor bp, bp       ; keep an entry count in bp
   mov edx, 0x0534D4150 ; Place "SMAP" into edx
   mov eax, 0xe820
   mov [es:di + 20], dword 1    ; force a valid ACPI 3.X entry
   mov ecx, 24      ; ask for 24 bytes
   int 0x15
   jc short .failed1    ; carry set on first call means "unsupported function"
   mov edx, 0x0534D4150 ; Some BIOSes apparently trash this register?
   cmp eax, edx     ; on success, eax must have been reset to "SMAP"
   jne short .failed2
   test ebx, ebx        ; ebx = 0 implies list is only 1 entry long (worthless)
   je short .failed3
   jmp short .jmpin

.e820lp:
   mov eax, 0xe820      ; eax, ecx get trashed on every int 0x15 call
   mov [es:di + 20], dword 1    ; force a valid ACPI 3.X entry
   mov ecx, 24      ; ask for 24 bytes again
   int 0x15
   jc short .e820f      ; carry set means "end of list already reached"
   mov edx, 0x0534D4150 ; repair potentially trashed register

.jmpin:
   jcxz .skipent        ; skip any 0 length entries
   cmp cl, 20       ; got a 24 byte ACPI 3.X response?
   jbe short .notext
   test byte [es:di + 20], 1    ; if so: is the "ignore this data" bit clear?
   je short .skipent

.notext:
   mov ecx, [es:di + 8] ; get lower dword of memory region length
   or ecx, [es:di + 12] ; "or" it with upper dword to test for zero
   jz .skipent      ; if length qword is 0, skip entry
   inc bp           ; got a good entry: ++count, move to next storage spot
   add di, 24

.skipent:
   test ebx, ebx        ; if ebx resets to 0, list is complete
   jne short .e820lp

.e820f:
   mov [mmap_ent], bp   ; store the entry count
   clc          ; there is "jc" on end of list to this point, so the carry must be cleared

   mov ah, 0x0E       ; Teletype command
   mov bh, 0x00       ; Page number
   mov bl, 0x07       ; Attributes (7 == white foreground, black background)
   mov al, mmap_ent   ; Character to print
   int 0x10

   ret

.failed1:
   push eax
   push ebx
   mov ah, 0x0E       ; Teletype command
   mov bh, 0x00       ; Page number
   mov bl, 0x07       ; Attributes (7 == white foreground, black background)
   mov al, 70 ; Character 'F' to print
   int 0x10
   pop ebx
   pop eax

   stc          ; "function unsupported" error exit
   ret

.failed2:
   push eax
   push ebx
   mov ah, 0x0E       ; Teletype command
   mov bh, 0x00       ; Page number
   mov bl, 0x07       ; Attributes (7 == white foreground, black background)
   mov al, 71 ; Character 'G' to print
   int 0x10
   pop ebx
   pop eax

   stc          ; "function unsupported" error exit
   ret

.failed3:
   push eax
   push ebx
   mov ah, 0x0E       ; Teletype command
   mov bh, 0x00       ; Page number
   mov bl, 0x07       ; Attributes (7 == white foreground, black background)
   mov al, 72 ; Character 'H' to print
   int 0x10
   pop ebx
   pop eax

   stc          ; "function unsupported" error exit
   ret


   mmap_ent db 0
   failmsg db 0
   failmem db 'Failed', 0
   ;times 512-($-$$) db 0 
   ;dw 0xAA55

EDITED:

I used nasm memext.asm -o memext.com -l memext.lst . Used MagicISO to make a bootable image file memext.iso and used Windows disk burner to burn it to a DVD/RW. Loaded Oracle VM and made a new Virtual Machine with 256 Mb RAM, CD/DVD, Hard disk of 2GB. Booted with DVD for a cold boot test, does not print anything.

Also, I open Command Console and just typed memext and it gave 'F' as output.

You will need to read the ACPI tables on a PC (or other machines that support ACPI).

Note that this will not give you the total size as one number, but give you the memory size of each region of memory - on a simple machine, that may just be two or three regions (there are holes of "not real memory" at the 0xA0000-0xFFFFF and wherever the BIOS decides to put the "PCI-hole").

I suspect it won't be entirely trivial to fit the ACPI reader into a single sector, considering some of the boot sector only has around 400 bytes of space available (although if you completely skip the partition table, I suppose you can use almost all of the 512 bytes).

As to "how to call C/C++", you will not be able to fit any meaningful C or C++ program in less than several sectors. You will need to take a look at an OS bootloader, and see how they achieve the setup for the compiler (and in many cases, you will also need special tools to produce code that is at a particular location suitable to be loaded into the memory and directly executed). This page may be of help for that (I haven't read through it all, it may even tell how much memory you have): http://www.codeproject.com/Articles/36907/How-to-develop-your-own-Boot-Loader

EDIT: my mistake, the wiki is correct, just leaving this here because...

Looks like there's a typo in the wiki - the line:

mov edx,0x0534D4150

should look like:

mov edx,0x050414D53

Notice the bytes are in reverse order (since x86 is little endian).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM