Code: Select all
;=[code16]===================================================================;
org 100h
use16
;test if in v86
mov eax,cr0
test al,1
jz .noV86
retn
.noV86:
;get descriptors bases
xor eax,eax
mov ax,cs
mov [code16],ax
shl eax,4
push eax
mov word [descriptorCode32+2],ax
mov word [descriptorData32+2],ax
mov word [descriptorCode16+2],ax
shr eax,16
mov byte [descriptorCode32+4],al
mov byte [descriptorData32+4],al
mov byte [descriptorCode16+4],al
;load gdtr
pop eax
add eax,gdt
mov dword [gdtr+2],eax
lgdt fword [gdtr]
;open a20
in al,92h
or al,2
out 92h,al
;disable interrupts (+nmi)
cli
in al,70h
or al,80h
out 70h,al
;switch to PM
mov eax,cr0
or al,1
mov cr0,eax
;jump to selectorCode32
db 66h
db 0eah
dd $+6
dw selectorCode32
;=[code32]===================================================================;
use32
;initialize segment registers
push selectorData32
pop ss
mov esp,stackTop
push selectorData32
pop ds
;initialize eflags (clear nt)
pushfd
pop eax
and eax,0ffffbfffh
push eax
popfd
;jump to selectorCode16
db 0eah
dd $+6
dw selectorCode16
use16
;switch to real mode
mov eax,cr0
and al,0feh
mov cr0,eax
;load cs/clear cashe
db 0eah
dw $+4
code16 dw ?
;set ss/ds/sp
mov ax,cs
mov ss,ax
mov ds,ax
mov sp,0fffeh
;enable interrupts (+nmi)
in al,70h
and al,07fh
out 70h,al
sti
;get out
retn
;=[const32]==================================================================;
;selectors
selectorCode32=1000b
selectorData32=10000b
selectorCode16=11000b
selectorFlat=100000b
;=[data32]===================================================================;
;global descriptors table
align 8
gdt:
rb 8
descriptorCode32 db 0ffh,0ffh,0,0,0,10011010b,11001111b,0
descriptorData32 db 0ffh,0ffh,0,0,0,10010010b,11001111b,0
descriptorCode16 db 0ffh,0ffh,0,0,0,10011010b,0,0
descriptorFlat db 0ffh,0ffh,0,0,0,10010010b,11001111b,0
gdtr dw $-gdt-1
dd ?
;stack
rb 200h
stackTop: