Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
In my bootloader I'm having some trouble. I'm using interrupts to get the memory size and some funny things are happening, I call the 0x15 interrupt with ax = 0xe801 and after the interrupt guess what the value of ax is? its 0xe801. It's as if the interrupt was never called and in fact I can comment it out and get the same result, but somehow when I test to see if ax < 15MB, it passes the test, my code is very derivative of whats on the wiki but I'll post it anyway to be sure I didn't screw up, does anyone else have the problem? is it just a problem with bochs and qemu? they're all I've tested with and I believe the use the same bios. also int 0x12 works fine and so does int 0x15 with ah = 0x88. Anyone know if I did something wrong?
getuppermemoryxe801:
mov ax, 0xe801 ;set up the ax for the BIOS call
int 0x15 ;call BIOS interrupt
xor dx, dx ;set dx to 0
xor cx, cx ;set cx to 0
jc .memerror ;handle general error
test ax, ax
je .memerror ;raise an error if no memory is returned
cmp ah, 0x86
je .memerror ;raise an error if the BIOS doesn't support the function
cmp ah, 0x80
je .memerror ;raise an error if the our command was invalid
jcxz .useax ;if cx is 0 then try ax
mov ax, cx ;ax contains the number of KB between 1 and 16 MB
mov bx, dx ;bx contains the number of 64k blocks between 16 MB and 4 GB
.useax:
cmp ax, 0x3c00 ;sanity check, we shouldn't be getting more than 15 MB
ja .memerror
ret
.memerror:
call getuppermemoryx88 ;fallback to using ah = 0x88 method
ret
getuppermemoryxe801:
xor dx, dx ;set dx to 0
xor cx, cx ;set cx to 0
mov ax, 0xe801 ;set up the ax for the BIOS call
int 0x15 ;call BIOS interrupt
jc .memerror ;handle general error
test ax, ax
je .memerror ;raise an error if no memory is returned
cmp ah, 0x86
je .memerror ;raise an error if the BIOS doesn't support the function
cmp ah, 0x80
je .memerror ;raise an error if the our command was invalid
jcxz .useax ;if cx is 0 then try ax
mov ax, cx ;ax contains the number of KB between 1 and 16 MB
mov bx, dx ;bx contains the number of 64k blocks between 16 MB and 4 GB
.useax:
cmp ax, 0x3c00 ;sanity check, we shouldn't be getting more than 15 MB
ja .memerror
ret
.memerror:
call getuppermemoryx88 ;fallback to using ah = 0x88 method
ret
Have you, by chance, modified your interrupt table (either on purpose, or by accident?). Or written over your Reserved BIOS area?
Check the dword at address 0x0054. It should be 0xf000f859.
The byte at 0xf00f859 is 0x9c (pushf).
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
Hmm... so after more testing I've found that the code I posted only fails when called as a subroutine. When the "call" instruction is replaced with the body of the subroutine then it works. I'm stumped.
Also I think it's relevant to mention that this code is called after only storing a the dl register in ram then setting up the stack, as far as I can tell the interrupts aren't touched.