;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³           PMode Tutorial (c) 1996 MATTsoft, All rights reserved.          ³
;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;³   THiS iS EXAMPLE (8th) IRQ0 & IRQ1 & exception handlers, wait until ESC  ³
;³                    úúúúúúúúúúúúú 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:  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
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
        mov eax,offset SampleInt
        add ds:[IDT_0],ax
        add ds:[IDT_1],ax
        add ds:[IDT_2],ax
        add ds:[IDT_3],ax
        add ds:[IDT_4],ax
        add ds:[IDT_5],ax
        add ds:[IDT_6],ax
        add ds:[IDT_7],ax
	mov eax,offset IRQ_0
        add ds:[IDT_08],ax
        mov eax,offset IRQ_1
        add ds:[IDT_09],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 0EAh
        dw 0
        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_Size = ($-GDT_0)
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú

CORE32_idx  = 08h
CODE32_idx  = 10h
DATA32_idx  = 18h
STACK32_idx = 20h
CODE16_idx  = 28h
DATA16_idx  = 30h

;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
; Interrupt Descriptor Table
IDT             dw IDT_size
                dd offset IDT_0
                ;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
IDT_0           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_1           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_2           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_3           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_4           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_5           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_6           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_7           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_08          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_09          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_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

; ÛÛÛÛ Start32 Must be AT OFFSET 0000h !!!! ÛÛÛÛ
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
        sti

        call main

__err_exit32:
        db 0eah
	dw offset Exit16
	dw 0
	dw CODE16_idx
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
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 esi
	push edi
	push eax
	push ecx

	mov ax,DATA32_idx
	mov ds,ax
	mov ax,CORE32_idx
	mov es,ax
        mov esi,offset Int_Msg
        mov edi,VIDEO_SEG+800
	mov ah,0eh
	mov ecx,36
@@1:	lodsb
	stosw
	loop @@1

	mov al,20h
	out 20h,al

	pop ecx
	pop eax
	pop edi
	pop esi
	jmp __err_exit32
	;iretd
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
main:   mov esi,offset My_Msg
	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
	sti
	mov ecx,1000000h
@@3:	cmp byte ptr ds:[MY_VAR],1
	jne @@3				; Wait until ESC
	xor ax,ax
	div ax				; This generates EXCEPTiON (x/0!!!)
        ret
;ùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùúùú
CODE32    ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
DATA32    SEGMENT
My_Msg  db 'Now in protected mode!'
Int_Msg db 'Processor EXCEPTION !!, terminating.'
Counter	db 0
MY_VAR	db 0
KeyPos	dd 1280
DATA32    ENDS
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
        END
