I am trying to develop an operating system. The design is this: I have a bootloader loaded at 0x7c00 which loads the second stage and jumps to it at 0x7e00. The second stage
In the second stage you load the third stage doing this:
Read:
mov ah , 02h ; Setup AH
mov al , 01h ; Setup AL
mov ch , 00h
mov cl , 03h
mov dh , 00h
mov dl , [0x500]
mov ax , 0x800 ; Destroy contents of AX
mov es , ax ; Setup ES=0x800
xor bx , bx
int 13h
I have marked the lines with the problems. You effectively set up AX to get ready for the read and then overwrite the values with 0x800 to set up ES. Move setting up ES before you setup AH and AL. Modify the code to look like:
Read:
mov ax , 0x800
mov es , ax ; Setup ES=0x800
mov ah , 02h ; Setup AH
mov al , 01h ; Setup AL
mov ch , 00h
mov cl , 03h
mov dh , 00h
mov dl , [0x500]
xor bx , bx
int 13h
This likely prevents your second stage from loading the 3rd stage properly.
At the end of the bootloader you have:
db 0xAA
db 0x55
This is backwards and should be:
db 0x55
db 0xAA
You could have written it as:
dw 0xAA55
The issue appears to be that you didn't take little endianness into account when defining these bytes.
You properly jump over the BIOS Parameter Block in the bootloader, but the BPB needs to start at the 4th byte in the boot sector. You can force a 2-byte JMP using the short
modifier. You can then place a nop
after the jump so that the BPB starts at the 4th byte.
Change:
jmp Reset
bpbOEM DB "SKULLOS "
To:
jmp short Reset
nop ; 1 byte padding as BPB needs to start at 4th byte (short jmp takes 2 bytes)
bpbOEM DB "SKULLOS "
mov sp , 0xFFFF
should probably be mov sp, 0x0000
. This is just a minor nitpick. Having the stack on a WORD boundary (even addresses) performs better on 8086 processors. Since you are not in real mode very long it doesn't much matter at all. Usually you'd use mov sp, 0x0000
in your case because the first WORD pushed will be at 0x9000:0xfffe since 2 is subtracted from SP first and then the WORD pushed onto the stack. Effectively with SP=0x0000 the stack will start by wrapping to the top of the 64k segment.
You don't need to JMP from label to label if the label is right after the JMP. Instructions like:
jmp Set
Set:
does nothing but waste space and take CPU cycles. I noticed you did that in quite a few places. This isn't part of your problem, just an observation. The FAR JUMP jmp (code-gdt_start):transfer_control
followed by the label is fine since that is used to to set the CS descriptor properly (for protected mode)
When doing disk access with int 13h
you should be using the boot drive number passed by the BIOS to your bootloader as the value for DL. Your first and second stages have code like:
mov dl , 00h
This always assumes you are reading from the first floppy (A:). If you want to use your code on a boot drive other than Floppy A: you'll want to remove this