;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³           PMode Tutorial (c) 1997 MATTsoft, All rights reserved.          ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³    THiS iS EXAMPLE (11th) v86 mode, but you can't go back to pmode :-(    ³
;³                    úúúúúúúúúúúúú G00D LuCK! úúúúúúúúúúúúú                 ³
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ

; þþþþþþþþþþþþþ IMPORTANT þþþþþþþþþþþþþþ
; ÛÛÛÛÛ Select your graphics card ÛÛÛÛÛÛ
 VIDEO_SEG equ 0B0000h	; for HERCULES
;VIDEO_SEG equ 0B8000h	; for VGA
; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

LOCALS @@
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
CODE16  SEGMENT BYTE PUBLIC 'CODE'
        ASSUME CS:CODE16,DS:DATA16
        .386
	.386P
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
Start:  jmp Next
	db 01bh,'[2J',0dh,'MATTsoft protected mode tutorial v1.0',01Ah,0
Next:	mov ax,DATA16
	mov ds,ax
	mov es,ax
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov ax,SS
        mov word ptr ds:[RealSSESP],ax
        mov dword ptr ds:[RealSSESP+2],esp
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        call CheckProcessor                     ; Check if 386+
	call CheckV86				; Check V86 mode
        call EnableA20
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        ; TODLE SE MUSI PREMISTIT DO FUNKCE!!!
	ASSUME DS:DATA32
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,DATA32
        mov ds,ax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        shl eax,4
        add dword ptr ds:[GDT+2],eax
        add dword ptr ds:[IDT+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,CODE16
        shl eax,4
        add dword ptr ds:[GDT_Code16+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,CODE32
        shl eax,4
        add dword ptr ds:[GDT_Code32+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,DATA32
        shl eax,4
        add dword ptr ds:[GDT_Data32+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,STACK32
        shl eax,4
        add dword ptr ds:[GDT_Stack32+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,DATA16
        shl eax,4
        add dword ptr ds:[GDT_Data16+2],eax
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor eax,eax
        mov ax,DATA32
        shl eax,4
        add eax,offset TASK0
        add dword ptr ds:[GDT_task0+2],eax
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov edi,offset IDT_exc
        ;
        mov eax,offset ExceptionHandler00
        add ds:[di],ax
        add di,8
        ;
        add di,8*3
        ;
        mov eax,offset ExceptionHandler04
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler05
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler06
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler07
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler08
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler09
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler0a
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler0b
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler0c
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler0d
        add ds:[di],ax
        add di,8
        ;
        mov eax,offset ExceptionHandler0e
        add ds:[di],ax
        add di,8
        ;
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov eax,offset IRQ_0
        add ds:[IDT_IRQ0],ax
        mov eax,offset IRQ_1
        add ds:[IDT_IRQ1],ax
        mov eax,offset V86Return
	add ds:[IDT_V86],ax
        mov eax,offset SampleInt
        add ds:[IDT_a],ax
        add ds:[IDT_b],ax
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        cli
        lgdt fword ptr ds:[GDT]                 ; Load GDTR
        lidt fword ptr ds:[IDT]
        mov eax,cr0
        or al,1
        mov cr0,eax                             ; Set Pmode
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	ASSUME DS:DATA16
	db 66h
        db 0EAh
        dd offset Start32
        dw CODE32_idx
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
Exit16:
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        cli
        mov eax,cr0
        xor al,1
        mov cr0,eax                             ; Return back to real :-(
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov ax,DATA16
        mov ds,ax
        mov es,ax
        mov ax,word ptr ds:[realSSESP]          ; Restore DOS stack
        mov esp,dword ptr ds:[realSSESP+2]
        lidt fword ptr ds:[IDT_Real]            ; Restore real-mode IDT
        sti
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov ax,4c00h
        int 21h                                 ; ... and terminate
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;                               $0ME R0UTiNES...

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Checks if the processor is 386+
CheckProcessor:
	pushf			; save flags for later
        xor ah,ah               ; clear high byte
        push ax                 ; push AX on the stack
	popf			; pop this value into the flag register
	pushf			; push flags on the stack
        pop ax                  ; ...and get flags into AX
        and ah,0f0h             ; try to set the high nibble
        cmp ah,0f0h             ; on a 80386, the high nibble can never be 0f0h
        je @@1                  ; ...
        mov ah,70h              ; now try to set NT and IOPL
        push ax                 ;
        popf                    ;
        pushf                   ;
        pop ax                  ;
        and ah,70h              ; if they couldn't be modified, no 386 is installed
        jz @@1                  ; ...
	popf			; restore flags
        retn                    ; and return
@@1:    mov dx,offset no386err  ; if there is no 386, exit with error msg
        mov ah,9
        int 21h
        mov ax,4c01h
        int 21h

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Checks if in V86 mode
CheckV86:
        smsw ax                 ; mov eax,cr0 is not allowed in V86
        test al,1               ; Test for V86
        jnz @@1
        ret
@@1:    mov dx,offset InV86err  ; if in V86, exit with error msg
        mov ah,9
        int 21h
        mov ax,4c02h
        int 21h
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Enable A20 gate
EnableA20:
        mov ah,11011111b
        call GateA20
        or al,al
        jnz @@1
        ret
@@1:    mov dx,offset A20err
        mov ah,9
        int 21h
        mov ax,4C03h
        int 21h
GateA20:cli
        call @@2
        jnz @@1
        mov al,0d1h
        out 64h,al
        call @@2
        jnz @@1
        mov al,ah
        out 60h,al
        call @@2
@@1:    ret
@@2:    push cx
        sub cx,cx
@@3:    in al,64h
        and al,00000010b
        loopnz @@3
        pop cx
        ret

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
CODE16  ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
DATA16  SEGMENT PARA PUBLIC 'DATA' USE16

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Error messages
no386err db '386 is needed!',13,10,'$'
InV86err db 'Processor is in V86 mode!',13,10,'$'
A20err   db 'A20 error!!!',13,10,'$'

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Real-mode IDT
IDT_Real        dw      03FFh,0,0               ; addr=0000:0000, size=3ffh

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Real-mode SS:ESP
RealSSESP dw 0,0,0


DATA16  ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
DATA32  SEGMENT PARA PUBLIC 'DATA32' USE32
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Global Descriptor Table
GDT     	dw GDT_Size			; Limit[0..15]
		dd offset GDT_0			; Base[0..32]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_0           dw 0                            ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 0                            ; AR[]
                db 0                            ; Info[]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Core32      dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10010010b                    ; AR[P=1,DPL=0,ED=0,W=1,A=0]
                db 11001111b                    ; Info[G=1,s=1], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Code32      dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10011010b                    ; AR[P=1,DPL=0,C=0,R=1,A=0]
                db 11001111b                    ; Info[G=1,s=0], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Data32      dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10010010b                    ; AR[P=1,DPL=0,ED=0,W=1,A=0]
                db 11001111b                    ; Info[G=1,s=1], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Stack32     dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10010010b                    ; AR[P=1,DPL=0,ED=0,W=1,A=0]
                db 11001111b                    ; Info[G=1,s=1], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Code16      dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10011010b                    ; AR[P=1,DPL=0,C=0,R=1,A=0]
                db 00000000b                    ; Info[G=0,s=0], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Data16      dw 0ffffh                       ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10010010b                    ; AR[P=1,DPL=0,ED=0,W=1,A=0]
                db 00000000b                    ; Info[G=1,s=1], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Task0       dw 67h                          ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 10001001b                    ; v86task
                db 00000000b                    ; Info[G=0,s=0], Limit[16..19]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
GDT_Size = ($-GDT_0)
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú

CORE32_idx  = 08h
CODE32_idx  = 10h
DATA32_idx  = 18h
STACK32_idx = 20h
CODE16_idx  = 28h
DATA16_idx  = 30h
TASK0_idx   = 38h

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Interrupt Descriptor Table
IDT             dw IDT_size
                dd offset IDT_Exc
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_Exc         dw 10h dup (0,CODE32_idx,8e00h,0)
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_IRQ0        dw 0                            ; Offset[0..15]
                dw CODE32_idx                   ; Selector[0..15]
                db 0                            ; Zero
                db 10001110b                    ; Flags[P=1,DPL=0,T=0]
                dw 0                            ; Offset[16..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_IRQ1        dw 0                            ; Offset[0..15]
                dw CODE32_idx                   ; Selector[0..15]
                db 0                            ; Zero
                db 10001110b                    ; Flags[P=1,DPL=0,T=0]
                dw 0                            ; Offset[16..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_V86         dw 0                            ; Offset[0..15]
                dw CODE32_idx                   ; Selector[0..15]
                db 0                            ; Zero
                db 10001110b                    ; Flags[P=1,DPL=0,T=0]
                dw 0                            ; Offset[16..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_A           dw 0                            ; Offset[0..15]
                dw CODE32_idx                   ; Selector[0..15]
                db 0                            ; Zero
                db 10001110b                    ; Flags[P=1,DPL=0,T=0]
                dw 0                            ; Offset[16..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_b           dw 0                            ; Offset[0..15]
                dw CODE32_idx                   ; Selector[0..15]
                db 0                            ; Zero
                db 10001110b                    ; Flags[P=1,DPL=0,T=0]
                dw 0                            ; Offset[16..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_size = ($-IDT_Exc)
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú

IDT_exc0	equ IDT_exc+00h
IDT_exc1	equ IDT_exc+08h
IDT_exc2	equ IDT_exc+10h
IDT_exc3	equ IDT_exc+18h
IDT_exc4	equ IDT_exc+20h
IDT_exc5	equ IDT_exc+28h
IDT_exc6	equ IDT_exc+30h
IDT_exc7	equ IDT_exc+38h
IDT_exc8	equ IDT_exc+40h
IDT_exc9	equ IDT_exc+48h
IDT_exca	equ IDT_exc+50h
IDT_excb	equ IDT_exc+58h
IDT_excc	equ IDT_exc+60h
IDT_excd	equ IDT_exc+68h
IDT_exce	equ IDT_exc+70h
IDT_excf	equ IDT_exc+78h
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Task State Segment 0
TASK0   label byte
TASK0_back    dd TASK0_idx
TASK0_esp0    dd 0
TASK0_sp0     dd STACK32_idx
TASK0_esp1    dd 0
TASK0_sp1     dd 0
TASK0_esp2    dd 0
TASK0_sp2     dd 0
TASK0_ocr3    dd 0
TASK0_oeip    dd 0
TASK0_oeflags dd 0
TASK0_oeax    dd 0
TASK0_oecx    dd 0
TASK0_oedx    dd 0
TASK0_oebx    dd 0
TASK0_oesp    dd 0
TASK0_oebp    dd 0
TASK0_oesi    dd 0
TASK0_oedi    dd 0
TASK0_oes     dd CORE32_idx
TASK0_ocs     dd CODE32_idx
TASK0_oss     dd STACK32_idx
TASK0_ods     dd DATA32_idx
TASK0_ofs     dd 0
TASK0_ogs     dd 0
TASK0_oldtr   dd 0
TASK0_iomap   dd 104 shl 16
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Local Descriptor Table
LDT     	dw LDT_Size			; Limit[0..15]
		dd offset LDT_0			; Base[0..32]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
LDT_0           dw 0                            ; Limit[0..15]
                db 0,0,0                        ; Base[0..23]
                db 0                            ; AR[]
                db 0                            ; Info[]
                db 0                            ; Base[24..31]
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
LDT_size = $-LDT_0
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Exception handler messages
ExceptionMsg	db 'Processor exception: ',0
Exception0Msg	db 'Division by zero.',0
Exception4Msg	db 'Overflow.',0
Exception5Msg	db 'Bound check.',0
Exception6Msg	db 'Invalid opcode.',0
Exception7Msg	db 'Processor extension not available.',0
Exception8Msg	db 'Double fault.',0
Exception9Msg	db 'Reserved!!!!',0
ExceptionaMsg	db 'Invalid Task State Segment (TSS).',0
ExceptionbMsg	db 'Segment not present.',0
ExceptioncMsg	db 'Stack Fault.',0
ExceptiondMsg	db 'General protection fault (GPF :-).',0
ExceptioneMsg	db 'Page fault.',0
Exception_eax	db ' eax=',0
Exception_ebx	db ' ebx=',0
Exception_ecx	db ' ecx=',0
Exception_edx	db ' edx=',0
Exception_esi	db ' esi=',0
Exception_edi	db ' edi=',0

Exception_cs	db '  cs=',0
Exception_ds	db '      ds=',0
Exception_es	db '      es=',0
Exception_fs	db '      fs=',0
Exception_gs	db '      gs=',0
Exception_ss	db '      ss=',0

Exception_ebp	db ' ebp=',0
Exception_eip	db ' eip=',0
Exception_esp	db ' esp=',0

Exception_cr2	db ' cr2=',0
Exception_cr3	db ' cr3=',0
Exception_dr7	db ' dr7=',0

Exception_fl	db ' eflags=',0
Exception_cr0	db ' cr0=',0

Exception_stk	db 'Stack: ',0
Exception_code	db 'Code:  ',0
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú

DATA32  ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
STACK32 SEGMENT BYTE PUBLIC 'STACK32' USE32
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
STACK32_stk  db 100h dup (0)
STACK32_end label byte
STACK32_size = (STACK32_end-STACK32_stk)
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
STACK32 ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
CODE32  SEGMENT PARA PUBLIC 'CODE32' USE32
	ASSUME CS:CODE32,DS:DATA32

; ÛÛÛÛ Hi coder, this routine may be at any offset :-) ÛÛÛÛ
Start32:
	mov ax,CORE32_idx
	mov es,ax
	mov fs,ax
	mov gs,ax
	mov ax,DATA32_idx
	mov ds,ax
        mov ax,STACK32_idx
	mov ss,ax
	mov esp,offset STACK32_end

	mov bx,1810h
        call set8529

        mov dword ptr ds:[TASK0_esp0],esp

        sti

        call main
_exit:
__err_exit32:
	cli
        mov bx,7008h
        call set8529                            ; Reset old IRQs
        db 0eah
	dw offset Exit16
	dw 0
	dw CODE16_idx
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
set8529:                                ; Set new IRQ vektor numbers
        mov al,11h                      ;  BL - low vektor base #
        out 20h,al                      ;  BH - high vektor base #
        jmp short $+2
        mov al,bl
        out 21h,al
        jmp short $+2
        mov al,4h
        out 21h,al
        jmp short $+2
        mov al,1h
        out 21h,al
        jmp short $+2
        mov al,11h
        out 0a0h,al
        jmp short $+2
        mov al,bh
        out 0a1h,al
        jmp short $+2
        mov al,2h
        out 0a1h,al
        jmp short $+2
        mov al,1h
        out 0a1h,al
        ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler00:
	push ebx
	mov ebx,offset Exception0Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler04:
	push ebx
	mov ebx,offset Exception4Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler05:
	push ebx
	mov ebx,offset Exception5Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler06:
	push ebx
	mov ebx,offset Exception6Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler07:
	push ebx
	mov ebx,offset Exception7Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler08:
	push ebx
	mov ebx,offset Exception8Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler09:
	push ebx
	mov ebx,offset Exception9Msg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler0a:
	push ebx
	mov ebx,offset ExceptionaMsg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler0b:
	push ebx
	mov ebx,offset ExceptionbMsg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler0c:
	push ebx
	mov ebx,offset ExceptioncMsg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler0d:
	push ebx
	mov ebx,offset ExceptiondMsg
        jmp short ExceptionHandler
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler0e:
	push ebx
	mov ebx,offset ExceptioneMsg
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
ExceptionHandler:
	; CS:		;+44
	; EIP		;+40
	;push ebx	;+36
	push eax	;+32
	push ecx	;+28
	push edx	;+24
	push esi	;+20
	push edi	;+16
	push ebp	;+12
	push ds		;+8
	push es		;+4
	pushfd		;+0
	cli

	mov ax,DATA32_idx
	mov ds,ax
	mov ax,CORE32_idx
	mov es,ax
        mov edi,VIDEO_SEG+160*9
	mov ah,1eh
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov al,'þ'
	mov ecx,80
	rep stosw
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        xor al,al
	mov ecx,80*7
        rep stosw
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov al,'þ'
	mov ecx,80
	rep stosw
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov edi,VIDEO_SEG+160*10
        mov esi,offset ExceptionMsg
	call @@DisplayMsg
	mov esi,ebx
	call @@DisplayMsg
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov edi,VIDEO_SEG+160*11
	mov esi,offset Exception_eax
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+32]
	call @@DisplayDWord
	mov esi,offset Exception_ebx
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+36]
	call @@DisplayDWord
	mov esi,offset Exception_ecx
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+28]
	call @@DisplayDWord
	mov esi,offset Exception_edx
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+24]
	call @@DisplayDWord
	mov esi,offset Exception_esi
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+20]
	call @@DisplayDWord
	mov esi,offset Exception_edi
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+16]
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov edi,VIDEO_SEG+160*12
	mov esi,offset Exception_cs
	call @@DisplayMsg
	mov bx,word ptr ss:[esp+44]
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_ds
	call @@DisplayMsg
	mov bx,word ptr ss:[esp+8]
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_es
	call @@DisplayMsg
	mov bx,word ptr ss:[esp+4]
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_fs
	call @@DisplayMsg
	mov bx,fs
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_gs
	call @@DisplayMsg
	mov bx,gs
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_ss
	call @@DisplayMsg
	mov bx,ss
	call @@DisplayWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov edi,VIDEO_SEG+160*13
	mov esi,offset Exception_ebp
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+12]
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_esp
	call @@DisplayMsg
	mov ebx,esp
	add ebx,40
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_eip
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp+40]
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_cr2
	call @@DisplayMsg
	mov ebx,cr2
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_cr3
	call @@DisplayMsg
	mov ebx,cr3
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_dr7
	call @@DisplayMsg
	mov ebx,dr7
	call @@DisplayDWord
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov edi,VIDEO_SEG+160*14
	mov esi,offset Exception_fl
	call @@DisplayMsg
	mov ebx,dword ptr ss:[esp]
	call @@DisplayBin
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov esi,offset Exception_cr0
	call @@DisplayMsg
	mov ebx,cr0
	call @@DisplayBin
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov edi,VIDEO_SEG+160*15
	mov esi,offset Exception_stk
	call @@DisplayMsg
	mov esi,esp
	add esi,54
	push ds
	push ss
	pop ds
	mov ecx,14
@@2:	xchg ax,bx
	std
	lodsw
	cld
	xchg bx,ax
	call @@DisplayWord
	mov al,' '
	stosw
	loop @@2
	pop ds
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	mov edi,VIDEO_SEG+160*16
	mov esi,offset Exception_code
	call @@DisplayMsg
	mov esi,dword ptr ss:[esp+40]
	xor ecx,ecx
	mov cx,CODE32
	shl ecx,4
	add esi,ecx
	mov ecx,24
	push ds
	push es
	pop ds
@@3:	xchg al,bl
	lodsb
	xchg bl,al
	call @@DisplayByte
	mov al,' '
	stosw
	loop @@3
	pop ds
        ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
	jmp __err_exit32
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
@@DisplayBin:
        mov cx,32
@@DisplayBi1:
        mov edx,1
	dec cl
        shl edx,cl
	inc cl
        push ebx
        and ebx,edx
        jnz @@DisplayBi2
        mov al,'0'
        jmp short @@DisplayBi3
@@DisplayBi2:
        mov al,'1'
@@DisplayBi3:
        stosw
        pop ebx
        loop @@DisplayBi1
        ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
@@DisplayMsg:
	lodsb
	or al,al
	jz @@DisplayMsg2
	stosw
	jmp short @@DisplayMsg
@@DisplayMsg2:
	ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
@@DisplayByte:				; Display BL as HeX!, modifikuje al
	mov al,bl
	shr al,4
	cmp al,0ah
	jb @@DisplayB1
	add al,'A'-0Ah
	jmp short @@DisplayB2
@@DisplayB1:add al,'0'
@@DisplayB2:stosw
	mov al,bl
	and al,0Fh
	cmp al,0Ah
	jb @@DisplayB3
	add al,'A'-0Ah
	jmp short @@DisplayB4
@@DisplayB3:add al,'0'
@@DisplayB4:stosw
	ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
@@DisplayWord:
	xchg bh,bl
	call @@DisplayByte
	xchg bh,bl
	call @@DisplayByte
	ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
@@DisplayDWord:
	push ebx
	shr ebx,16
	call @@DisplayWord
	pop ebx
	call @@DisplayWord
	ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
CODE32    ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
CODE32    SEGMENT
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IRQ_0:  push edi
	push eax
        push es
	push ds

        mov ax,CORE32_idx
	mov es,ax
	mov ax,DATA32_idx
	mov ds,ax
        mov edi,VIDEO_SEG+158                           ; x=78:y=1
        inc byte ptr ds:[Counter]
        mov ah,0eh
	mov al,ds:[Counter]
        stosw

	mov al,20h
        out 20h,al                                      ; EOI

	pop ds
        pop es
        pop eax
	pop edi
        iretd
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IRQ_1:
	push esi
	push edi
	push eax
	push ecx
        push ds
        push es

        mov ax,DATA32_idx
        mov ds,ax
        mov ax,CORE32_idx
        mov es,ax

	mov ah,0eh
        add ds:[KeyPos],6
	in al,60h
	mov cl,al
        mov ds:[MY_VAR],al
	mov edi,VIDEO_SEG
        add edi,ds:[KeyPos]
	shr al,4
	cmp al,0ah
	jb @@a1
	add al,'A'-0Ah
	jmp @@a2
@@a1:	add al,'0'
@@a2:	stosw
	mov al,cl
	and al,0fh
	cmp al,0ah
	jb @@b1
	add al,'A'-0Ah
	jmp @@b2
@@b1:	add al,'0'
@@b2:	stosw

	mov al,20h
	out 20h,al

        pop es
        pop ds
	pop ecx
	pop eax
	pop edi
	pop esi
        iretd
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
SampleInt:
	push eax

	mov al,20h
	out 20h,al
	pop eax
	iretd
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
V86Return:
	mov ax,CODE32_idx
	mov es,ax
	xor edi,edi
	mov ecx,4000
	rep stosw
	jmp _exit
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
main:   mov esi,offset My_Msg


	mov dx,3b4h
	mov al,14
	out dx,al
	inc dx
	mov al,1
	out dx,al

	mov edi,VIDEO_SEG
	mov ecx,80*25
	xor ax,ax

	rep stosw

	mov edi,VIDEO_SEG+640
	mov ah,0eh
	mov ecx,22
@@2:	lodsb
	stosw
	loop @@2

@@3:	cmp ds:[MY_VAR],1
	jne @@3
	
	mov ax,TASK0_idx
	ltr ax
 
	mov ds:[MY_VAR],0
	
	pushfd
	pop eax
	or eax,1 shl 17
	push eax
	mov eax,CODE32_idx
	push eax
	push offset NextM
	iretd

NextM:	cmp ds:[MY_VAR],1
	jne n2
	jmp _exit
n2:
		; create sample code on 0000:0000
	mov ax,CORE32_idx
	mov es,ax
	mov byte ptr es:[0],0ebh
	mov byte ptr es:[1],0feh	; jmp 0:00 :-)
	mov byte ptr es:[2],000h	; jmp 0:00 :-)

	pushfd
	push CODE32_idx
	push offset _exit
	
	mov eax,1
	push eax
	push eax
	push eax
	push eax
	push eax
	push eax
	push eax
	push eax			; Make ZER0 space on stack!
					; ...and n0w eflagz
	
	mov eax,00023202h		; set VM
	push eax			; eflagz

	mov eax,CODE16			; This is 0LD D0Z 16bit C0DE!!!
	push eax			; CS: (?? CS)
	mov eax,offset V86Code
	push eax			; EIP (32bit)

	mov edi,VIDEO_SEG
	mov ecx,80*25
	mov ah,0eh
	mov al,176
	rep stosw

	iretd				; Initalize V86 mode
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
CODE32    ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
DATA32    SEGMENT
My_Msg  db 'Now in protected mode!'
Counter	db 0
MY_VAR	db 0
KeyPos	dd 1280
DATA32    ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
CODE16  SEGMENT BYTE PUBLIC 'CODE' USE16
        ASSUME CS:CODE16,DS:DATA16
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú

V86Code:
	cli
	mov ax,9000h
	mov ss,ax
	mov sp,200h
	sti
	mov ax,DATA16
	mov ds,ax
	mov ax,VIDEO_SEG/16
	mov es,ax
	mov si,offset V86Mess
	mov di,160*2
@@1:	lodsb
	cmp al,'$'
	je @@2
	mov ah,70h
	stosw
	jmp short @@1
@@2:	jmp $


CODE16  ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
DATA16  SEGMENT

v86Mess	db 'This message was printed in v86 mode.'
	db '    This is very stupid example, so It cannot make LFs.'
	db '    I think, that this is enough.'
	db '$'

DATA16	ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
        END
