I'm building a personal bootloader because, well, because I think it's an interesting project. I'm currently working on getting a memory map from the BIOS, but since I'm still in real mode without a GDT, etc. I'm unsure whether my code worked. It doesn't produce any errors, and I *think* I set up any error-checking correctly, but I'm not quite sure. Is there any way to 'test' this memory map while still in my second-stage bootloader, or would it be more practical to keep going until I get to the kernel part, and then see if passing the table works?
My second question is about where I'm keeping the table and the number of entries in memory. Again, I *think* I've done this properly, but I am admittedly new at designing bootloaders (you have to start somewhere, of course), and the inability to check whether it's working doesn't exactly make things easier. Right now, I'm storing BP at the end of the loop at 0x0000:0x7e00, and I changed ES:DI to 0x0000:0x7e02. BP is 2 bytes long, so that shouldn't pose any problems when trying to pass it to the kernel later, right?
Basically, I'm not seeing anything unexpected happen in my bootloader, but then again I mostly learn by experimenting around, and there's very little indication whether you're doing the right thing(TM) or not when trying to code a bootloader. Any advice would be much appreciated.
For those who're interested, the code I'm using to map the memory is pretty much identical to the one found here, so don't expect to find many surprising elements. I posted it below for those who want to look it, just in case. (Don't mind the rambling comments. They're... Ah, well, it gives you some idea of how my mind works while I'm coding.)
Code: Select all
; Try to get a map of the available RAM by using BIOS interrupts. Joy of joys.
memMap:
; First, we set up the registers. The idea is to store the memory map
; at 0x7e00, so we set ES:DI to 0x0000:0x7e00. We also have to store
; a signature, and a stupid value in EAX to get our interrupt to work.
xor ax, ax
mov es, ax
mov bp, ax
mov di, 0x7e02
xor ebx, ebx
mov edx, 0x0534d4150
mov eax, 0xe820
mov [es:di + 20], dword 1
mov ecx, 24
int 0x15
; Some mandatory tests to see if this particular interrupt is supported
; and works as expected.
jc .memMap_fail
mov edx, 0x0534d4150
cmp eax, edx
jne .memMap_fail
test ebx, ebx
je .memMap_fail
; Great, now let's jump to the bulk of the work.
jmp .memMap_jump
; "There once was a loop-y named Ragnar the Red..."
.memMap_loop:
mov eax, 0xe820
mov [es:di + 20], dword 1
mov ecx, 24
int 0x15
jc .memMap_end ; CF implies the end of the list has been reached.
mov edx, 0x0534d4150
.memMap_jump:
jcxz .memMap_skip
cmp cl, 20
jbe .memMap_notext
test byte [es:di + 20], 1
je .memMap_skip
.memMap_notext:
mov ecx, [es:di + 8]
or ecx, [es:di + 12]
jz .memMap_skip
inc bp
add di, 24
.memMap_skip:
test ebx, ebx
jne .memMap_loop
; The end of the memory map procedures. All that's left to do is storing BP at the
; beginning of a free piece of memory, and - how odd! - we happen to have 2 more bytes
; of free RAM at 0x7e00+1.
.memMap_end:
mov ax, 0x7e00
mov di, ax
mov [es:di], bp
clc
mov si, memGoodMsg
call showMsg
ret
; Well, clearly *something* went wrong. I can't be bothered to use different error
; messages for all the different ways this may have gone wrong, given that I haven't
; had any errors with memory mapping so far. I might change this later if it turns out
; to become a problem.
.memMap_fail:
mov si, memFailMsg
call showMsg
cli
jmp $