This was resolved on SO in the comment area. But the main problem is that he's using real mode segments that aren't zero (ie: 0x7c0, 0x2000 eyc) base on BrokenThorne tutorial. Unfortunately this meant that the base in the GDT was a real mode offset and had to be converted to a linear address. The FAR JMP into protected mode also suffered the same kind of issue. Once in protected mode the offsets the code were running at were not relative to linear address 0x00000. I suggested a simplification of the code to have the jump to protected mode and the GDT in the first 64k and using a segment of 0x0000. This means a 16-bit offset in real mode in the first 64kb is the same as the offset in protected mode. No monkeying around by doing real mode offset to linear address conversions in protected mode. The drive number was hard coded to 0 instead of the one passed in by the BIOS (via DL register) when doing a disk read. A quick fix was to simplify the code he posted to something like the code below. start.asm:
Code:
org 0x7c00
bits 16
start:
xor ax, ax ; Set DS to 0. xor register to itselfzeroes register
mov ds, ax
mov ss, ax ; Stack just below bootloader SS:SP=0x0000:0x7c00
mov sp, 0x7c00
mov ah, 0x00
mov al, 0x03
int 0x10
load_kernel:
mov ah, 0x02 ; call function 0x02 of int 13h (read sectors)
mov al, 0x01 ; read one sector (512 bytes)
mov ch, 0x00 ; track 0
mov cl, 0x02 ; sector 2
mov dh, 0x00 ; head 0
; mov dl, 0x00 ; drive 0, floppy 1. Comment out DL passed to bootloader
xor bx, bx ; segment 0x0000
mov es, bx ; segments must be loaded from non immediate data
mov bx, 0x7E00 ; load the kernel right after the bootloader in memory
.readsector:
int 13h ; call int 13h
jc .readsector ; error? try again
jmp 0x0000:0x7E00 ; jump to the kernel at 0x0000:0x7e00
times 510-($-$$) db 0
dw 0xAA55
kernel.asm:
Code:
org 0x7e00 ; Offset of this code is 0x7e00
; as we loaded it into memory at 0x0000:0x7e00
bits 16
section .text
start:
cli
in al, 0x92
or al, 2
out 0x92, al
lgdt[toc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:start32 ; The FAR JMP is simplified since our segment is 0
section .rodata
gdt32:
dd 0
dd 0
dw 0x0FFFF
dw 0
db 0
db 0x9A
db 0xCF
db 0
dw 0x0FFFF
dw 0
db 0
db 0x92
db 0xCF
db 0
gdt_end:
toc:
dw gdt_end - gdt32 - 1
dd gdt32 ; The GDT base is simplified since our segment is now 0
bits 32
section .text
start32:
mov ax, 0x10
mov ds, ax
mov es, ax
mov ss, ax
mov esp, 0x9c000 ; Set the stack to grow down from area under BDA/Video memory
mov dword [0xB8000], 0x2f4b2f4f
jmp $