Informationen vom RM in den PM übergeben?
-
INT 12 - BIOS - GET MEMORY SIZE
Return: AX = kilobytes of contiguous memory starting at absolute address 00000h
Note: this call returns the contents of the word at 0040h:0013h; in PC and XT, this value is set from the switches on the motherboardWie kann man diesen Wert nach dem Abfragen beim Umschalten vom RM in den PM am einfachsten übergeben? Ich benötige den physikalischen Speicher. Bisherige Routinen, die ich gefunden habe, geben falsche Werte aus.
-
Im Allgemeinen kannst du für die Übergabe Register nehmen, einen festen Speicherbereich reservieren, der beiden Programmen bekannt ist, oder die Werte geschickt auf den Stack legen, sodass sie als Parameter fungieren.
Erhard Henkes schrieb:
INT 12 - BIOS - GET MEMORY SIZE
Return: AX = kilobytes of contiguous memory starting at absolute address 00000h
Note: this call returns the contents of the word at 0040h:0013h; in PC and XT, this value is set from the switches on the motherboard1. Diese Information steht im Speicher an der linearen Adresse 0x00000413
2. Das "contiguous" heißt "zusammenhängend". Das bedeutet, dass maximal 640KB zurückgegeben wird, denn bei 0x000a0000 ist bereits die erste Lücke. Also nützt dir dieser Wert nichts.Im Artikel auf wiki.osdev.org sind verschiedene Methoden beschrieben: http://wiki.osdev.org/Detecting_Memory_(x86)#Detecting_Upper_Memory
-
Danke! Diesen Artikel hatte ich bisher übersehen. Das osdev.org wiki ist echt klasse.
INT 0x15, EAX = 0xE820 ... available on all PCs built since 2002
Sieht kompliziert aus.
-
Erhard Henkes schrieb:
Sieht kompliziert aus.
Ich kann dir mal meinen Code dafür raussuchen, der hat zweistufig gearbeitet: BIOS-Access im RM und die Aufbereitung der Liste im PM. Hat auch, zumindest unter Bochs, geklappt
edit: Und funktioniert bisher nur bis 4GB RAM, müsste sich aber leicht ummünzen lassen. Die Daten werden an einem vordefinierten Platz im RAM gespeichert (bei RM->PM).
-
Es werden zwei Listen erstellt, eine Liste, die die freien Stücke enthält, die andere enthält die reservierten. Als "frei" gelten hier die Stücke mit Typ==1 (obwohl potentiell auch Typ3 & Typ4 nutzbar wären). Hab den Assembler-Code umgemodelt, dass auch >4GB gehen. Den C-Code, der die Stückchen dann an der Pagesize ausrichtet, überlappende Regionen zurechtschneidet und anschließend sortiert, poste ich jetzt nicht, weil er sehr davon abhängt, wie du den freien physischen Speicher verwaltest. Ich hab bei mir einfach 'ne Liste mit freien Elementen, du hast ja Bitmaps. Da kannst du ja erst alles als reserviert markieren und anschließend die freien Stückchen mit Alignment nach innen eintragen. Die Daten bekommst du jedenfalls so:
struct MemChunk { uint64 addr; uint64 size; }; MemChunk* const free_list = (MemChunk*)0x0500; MemChunk* const resv_list = (MemChunk*)0x0D00; MemChunk* list; for ( list=free_list; list->size; ++list ) ...
; We store the RAM-info-lists at some free memory-place, see http://wiki.osdev.org/Memory_Map_(x86) ; There are two lists, each containing items of the form {addr:32, size:32}. This is, each entry ; is a 2-tuple with each member being a 32-bit unsigned integer. ; The first list is located at 0x0500 and lists the chunks of free memory. ; The second list is located at 0x0D00 and lists the chunks of reserved memory. ; ; Doc: http://wiki.osdev.org/Detecting_Memory_(x86)#Getting_an_E820_Memory_Map ; http://forum.osdev.org/viewtopic.php?f=1&t=18336&hilit=*E801* ; http://www.ctyme.com/intr/rb-1741.htm#Table581 GetRamChunks: xor ebx, ebx .get_entry: ; Set up the BIOS-call mov edi, .chunk_base mov eax, 0xE820 mov edx, 0x534D4150 mov ecx, 24 int 0x15 ; Carry-flag indicates "done" if eax is 534D4150h jnc .continue_checking cmp eax, 0x534D4150 jne .fail jmp .done .continue_checking: cmp eax, 0x534D4150 jne .fail .success: ; The entry may be useless for us (size==0) cmp dword [.chunk_size], 0 jne .size_not_null cmp dword [.chunk_size+4], 0 jne .size_not_null jmp .continue .size_not_null: cmp dword [.chunk_type], 1 jne .is_reserved_ram .is_free_ram: mov eax, .listfree jmp .do_entry .is_reserved_ram: mov eax, .listresv .do_entry: ; Copy the 4 dwords to the list cld mov ecx, 4 mov esi, .chunk_base mov edi, [eax] rep movsd add dword [eax], 16 .continue: test ebx, ebx ; ebx=0 indicates end-of-list jne .get_entry .done: ; Do a empty (0,0) entry in both lists as a terminator xor eax, eax mov ecx, 4 mov edi, [.listfree] rep stosd add dword [.listfree], 16 xor eax, eax mov ecx, 4 mov edi, [.listresv] rep stosd add dword [.listresv], 16 ; Check whether there were too many entries cmp dword [.listfree], 0x500+2048 jge .fail cmp dword [.listresv], 0x500+2048+2048 jge .fail ret .fail: mov al, 'A' mov ah, 0x0E int 0x10 hlt .listfree: dd 0x500 .listresv: dd 0xD00 .chunk_base: times 2 dd 0 .chunk_size: times 2 dd 0 .chunk_type: dd 0 .chunk_extt: dd 0
-
Hallo Badestrand,
danke für die Unterstützung, finde ich klasse. Hier habe ich eine Umsetzung gefunden, die auch funktioniert: http://www.c-plusplus.net/forum/viewtopic-var-t-is-246159.html
http://www.henkessoft.de/OS_Dev/OS_Dev3.htm#mozTocId584885
-
Dieser Thread wurde von Moderator/in Nobuo T aus dem Forum Assembler in das Forum Projekt: OS-Development verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.