It works fine if "jmp $" before going back to real mode, but for some reason it doesn't like it. I feel like I'm missing some stupid mistake, maybe someone else will see what I overlooked.
(This code is basically the same code used in John Fine's BOOTF)
Code: Select all
[BITS 16], [ORG 0], STAGE1_ADDRESS is correct, interrupts off
...
lgdt [STAGE1_ADDRESS+gdtr]
mov ebx, cr0
or bl, 1
mov cr0, ebx
.0: in al, 0x64 ; enable A20
test al, 2
jnz .0
mov al, 0xD1
out 0x64, al
.1: in al, 0x64
and al, 2
jnz .1
mov al, 0xDF
out 0x60, al
mov ax, LINEAR_DATA_SEL
mov ds, ax
mov es, ax
and bl, 11111110b
mov cr0, ebx
jmp short $
...
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 16-bit limit/32-bit linear base address of GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdtr:
dw gdt_end-gdt-1 ; GDT limit
dd STAGE1_ADDRESS+gdt ; linear, physical address of GDT
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Global Descriptor Table (GDT)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
gdt:
; null descriptor
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear code segment descriptor
LINEAR_CODE_SEL equ $-gdt
dw 0xFFFF
dw 0
db 0
db 0x9A ; present, ring 0, code, non-conforming, readable
db 0xCF
db 0
; linear data segment descriptor
LINEAR_DATA_SEL equ $-gdt
dw 0xFFFF
dw 0
db 0
db 0x92 ; present, ring 0, data, expand-up, writbale
db 0xCF
db 0
gdt_end: