; Raw_protected_mode and V86_routinez (and paging !!!) examplez ...
; Diz made BLOOD

P486
org	0

	;
vmfl	=	02h
rffl	=	01h
ntfl	=	04000h
ioplfl	=	03000h
ofl	=	0800h
dfl	=	0400h
ifl	=	0200h
tfl	=	0100h
sfl	=	080h
zfl	=	040h
afl	=	010h
pfl	=	04h
cfl	=	01h
	;

descriptor	struc
sll	dw	?
bal	dw	?
bam	db	?
typ	db	?
slh	db	?
bah	db	?
descriptor	ends

stack_16	=	100h
stack_32	=	100h
stack_32_tss_	=	100h

code16	segment para public use16
	assume cs:code16, ds:code16
	;
	db	stack_16 dup(?)
stack_16_end	label	near
	;

	;
proc_error	db	'Sorry, ale potrebuju minimalne 80386ku ...', 0ah, 0dh, '$'
	;

check_processor:
	;
	lea dx, [proc_error]
	;
	xor ax, ax
	push ax
	popf
	pushf
	pop ax
	and ax, 0f000h
	cmp ax, 0f000h
	jz _error_
	;
	mov ax, 0f000h
	push ax
	popf
	pushf
	pop ax
	and ax, 0f000h
	jz _error_
	;
	retn
	;
	
	;
vm_mode	db	'Sorry, ale uz bezim ve VM8086_modu ...', 0ah, 0dh, '$'
	;

	;
check_vm_mode:
	;
	lea dx, [vm_mode]
	;
	mov eax, cr0
	;
	bt ax, 0
	jc _error_
	;
	retn
	;
	
	;
a20_error	db	'Sorry, ale nejde zapnout A20 ...', 0ah, 0dh, '$'
	;
at_a20handler:
; ax - 0 = vypnout a20
; ax - 1 = zapnout a20
; vystup - ax = 1 - v poradku
;          ax = 0 - chyba
	;
	or ax, ax
	jz short aahdisable
	;
aahenable:
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0d1h
	out 64h, al
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0dfh
	out 60h, al
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0ffh
	out 64h, al
	;
	call sync8042
	jnz short aaherr
	;
	jmp short aahexit
	;
aahdisable:
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0d1h
	out 64h, al
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0ddh
	out 60h, al
	;
	call sync8042
	jnz short aaherr
	;
	mov al, 0ffh
	out 64h, al
	;
	call sync8042
	;
aahexit:
	;
	mov ax, 1
	;
	retn
	;
aaherr:
	;
	lea dx, [a20_error]
	;
	jmp _error_
	;
sync8042:
	;
	xor cx, cx
	;
s8insync:
	;
	in al, 64h
	and al, 2
	;
	loopnz s8insync
	;
	retn
	;
addrezz_1	dw	80h, 00h
addrezz_2	dw	90h, 0ffffh
	;
A20_state:
	;
	push ds
	push es
	;
	les di, dword ptr [addrezz_2]
	lds si, dword ptr [addrezz_1]
	;
	mov cx, 4
	cld
	repe cmpsw
	;
	pop es
	pop ds
	;
	xor ax, ax
	jcxz $ + 3
	;
	inc ax
	;
	retn
	;

	;
_error_:
	;
	mov ah, 09h
	int 21h
	;
	mov ax, 4cffh
	int 21h
	;

	;
page_error	db	'Sorry, ale je malo memu pro PDBR ...', 0ah, 0dh, '$'
	;

	;	
start_16:
	;
	cli
	;
	mov ax, code16
	;
	mov ss, ax
	mov sp, offset stack_16_end
	;
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	;
	sti
	;
	mov ah, 51h
	int 21h
	;
	push es
	;
	mov es, bx
	;
	push bx
	;
	push word ptr es:[2ch]
	;
	mov ah, 49h
	pop es
	int 21h	
	;
	pop bx
	;
	mov ah, 4ah
	mov es, bx
	mov bx, last_segment
	sub bx, code16
	inc bx
	int 21h
	;
	mov ah, 48h
	mov bx, 2feh
	int 21h
	;
	lea dx, [page_error]
	jc _error_
	;
	movzx ebx, ax
	;
	shl ebx, 4
	;
	and ebx, not 0fffh
	;
	and ax, 0ffh
	;
	jz $ + 9
	;
	add ebx, 1000h
	;
	pop es
	;
	mov dword ptr [pdbr_entry], ebx
	;
	call check_processor
	call check_vm_mode
	call a20_state
	;
	xor ax, 01h
	;
	or ax, ax
	jz $ + 5
	;
	call at_a20handler
	;
	call init_basez
	;
	mov ax, code16
	movzx eax, ax
	;
	shl eax, 4
	;
	mov dword ptr ds:[_code16], eax
	;
	mov ax, code32
	movzx eax, ax
	;
	shl eax, 4
	;
	mov dword ptr ds:[_code32], eax
	;
	mov ax, code32_tss
	movzx eax, ax
	;
	shl eax, 4
	;
	mov dword ptr ds:[_code32_tss], eax
	;
	call prepare_pagez
	;
	mov ax, 03h
	int 10h
	;
	cli
	;
	db	66h, 0b8h
pdbr_entry	dd	?
	;
	mov cr3, eax
	;
	lgdt fword ptr ds:[_gdt_]
	lidt fword ptr ds:[_idt_]
	;
	mov eax, cr0
	or eax, 80000001h
	mov cr0, eax
	;
	db	0eah
	dw	small start_32, code_32_sel
	;
	
	;
idt_rm	dw	03ffh, 0, 0
	;
	
	;
real_mode_entry:
	;
	mov eax, cr0
	and eax, not 1
	mov cr0, eax
	;
	db	0eah
	dw	$ + 4, code16
	;
	mov ax, cs
	;
	mov ss, ax
	mov sp, offset stack_16_end
	;
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	;
	lidt fword ptr [idt_rm]
	;
	sti
	;
	xor ax, ax
	int 16h
	;
	mov ax, 03h
	int 10h
	;
	mov ax, 4c00h
	int 21h
	;
	
	;
base_table:
	;
	dw	(end_base_table - (offset base_table + 2)) shr 2
	;
	dw	0ffffh
	dw	code32
	;
	dw	small code_16_des
	dw	code16
	;
	dw	small data_16_des
	dw	code16
	;
	dw	small code_32_des
	dw	code32
	;
	dw	small data_32_des
	dw	code32
	;
	dw	small code_tss_des
	dw	code32_tss
	;
	dw	small data_tss_des
	dw	code32_tss
	;
	dw	small _gdt_
	dw	code32
	;
	dw	small _idt_
	dw	code32
	;
	dw	small tss_des
	dw	code32
	;
	dw	small tmp_tss_des
	dw	code32
	;
	dw	small ldt_des
	dw	code32
	;
end_base_table	label	near
	;

	;
init_basez:
	;
	push es
	;
	lea si, [base_table]
	lodsw
	;
	xchg ax, cx
	jcxz konec_init_basez
	;
init_basez_main_loop:
	;
	lodsw
	;
	cmp ax, 0ffffh
	jnz next_init_basez
	;
	lodsw
	mov es, ax
	;
	jmp go_2_next_entry_base
	;
next_init_basez:
	;
	xchg ax, bx
	;
	lodsw
	movzx eax, ax
	;
	shl eax, 4
	;
	add word ptr es:[bx.bal], ax
	;
	pushf
	;
	shr eax, 8
	;
	popf
	;
	adc byte ptr es:[bx.bam], ah
	;
go_2_next_entry_base:
	;
	loop init_basez_main_loop
	;
konec_init_basez:
	;
	pop es
	;
	retn
	;
	
	; Diz preparez 4 megabytez in one PDBR and 1024 PTEz
prepare_pagez:
	;
	mov eax, dword ptr [pdbr_entry]
	mov ebx, eax
	;
	shr ebx, 4
	;
	mov es, bx
	;
	xor di, di
	;
	add eax, 1000h
	or eax, 000000111b
	;
	stosd
	;
	xor eax, eax
	mov cx, 1023
	;
	rep stosd
	;
	add bx, 100h
	mov es, bx
	;
	xor di, di
	;
	or eax, 000000111b
	;
	mov cx, 1024
	;
main_loop:
	;
	stosd
	;
	add eax, 1000h
	;
	loop main_loop
	;
	retn
	;

	;
; Diz iz VM8086_code
vm_code:
	;
	xor eax, eax
	xor ebx, ebx
	xor ecx, ecx
	xor edx, edx
	xor esi, esi
	xor edi, edi
	xor ebp, ebp
	;
	mov ax, word ptr cs:[v86r_ax]
	mov bx, word ptr cs:[v86r_bx]
	mov cx, word ptr cs:[v86r_cx]
	mov dx, word ptr cs:[v86r_dx]
	mov si, word ptr cs:[v86r_si]
	mov di, word ptr cs:[v86r_di]
	mov bp, word ptr cs:[v86r_bp]
	;
	db	0cdh
vm8086_interrupt_number	db	?
	;
	mov word ptr cs:[v86r_ax], ax
	mov word ptr cs:[v86r_bx], bx
	mov word ptr cs:[v86r_cx], cx
	mov word ptr cs:[v86r_dx], dx
	mov word ptr cs:[v86r_si], si
	mov word ptr cs:[v86r_di], di
	mov word ptr cs:[v86r_bp], bp
	mov word ptr cs:[v86r_ds], ds
	mov word ptr cs:[v86r_es], es
	;
	pushf
	pop ax
	;
	mov word ptr cs:[v86r_flags], ax
	;
	int 0fdh
	;

	;
dos_return:
	;
	mov dx, last_segment
	sub dx, code16
	inc dx
	;
	mov ax, 3100h
	int 21h
	;

code16	ends

code32	segment para public use32
	assume cs:code32, ds:code32
	;
	db	stack_32 dup(?)
stack_32_end	label	near
	;
	
	; GDT_selectorz
code_32_sel	=	08h
data_32_sel	=	10h
code_16_sel	=	18h
data_16_sel	=	20h
core_sel	=	28h
gate_sel	=	30h
tss_sel		=	38h
tmp_tss_sel	=	40h
ldt_sel		=	48h
regz_sel	=	50h
	;
	
	; LDT_selectorz
code_tss_sel	=	0ch
data_tss_sel	=	14h
	;
	
	
	;
_gdt_	dw	gdt_length, small offset gdt_32, 0
	;
gdt_32		descriptor	<>
code_32_des	descriptor	<0ffffh, 0, 0, 10011010b, 11001111b, 0>
data_32_des	descriptor	<0ffffh, 0, 0, 10010010b, 11001111b, 0>
code_16_des	descriptor	<0ffffh, 0, 0, 10011010b, 0, 0>
data_16_des	descriptor	<0ffffh, 0, 0, 10010010b, 0, 0>
core_des	descriptor	<0ffffh, 0, 0, 10010010b, 11001111b, 0>
gate_des	descriptor	<small write_message, code_32_sel, 0, 10001100b, 0, 0>
tss_des		descriptor	<end_mon_tss - mon_tss, small mon_tss, 0, 10001001b, 0, 0>
tmp_tss_des	descriptor	<end_tmp_tss - tmp_tss, small tmp_tss, 0, 10001001b, 0, 0>
ldt_des		descriptor	<ldt_length, small ldt_32, 0, 10000010b, 0, 0>
regz_des	descriptor	<small show_regz, code_32_sel, 0, 10001100b, 0, 0>
	;
gdt_length	=	($ - offset gdt_32) - 1
	;
	
	;
_idt_	dw	idt_length, small offset idt_32, 0
	;
idt_32		descriptor	<small exception_0 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_1 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_2 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_3 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_4 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_5 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_6 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_7 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_8 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_9 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_a , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_b , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_c , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small vm8086_gen_prot , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small exception_e , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	17 dup(<small unexpected_exc, code_32_sel, 0, 10001110b, 0, 0>)
		descriptor	<small irq_0 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_1 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_2 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_3 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_4 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_5 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_6 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_7 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_8 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_9 , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_a , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_b , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_c , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_d , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_e , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small irq_f , code_32_sel, 0, 10001110b, 0, 0>
		descriptor	<small vm8086_int , code_32_sel, 0, 10001110b, 0, 0>
	;
idt_length	=	($ - offset idt_32) - 1
	;

	;
ldt_32		descriptor	<>
code_tss_des	descriptor	<0ffffh, 0, 0, 10011010b, 11001111b, 0>
data_tss_des	descriptor	<0ffffh, 0, 0, 10010010b, 11001111b, 0>

	;
ldt_length	=	$ - offset ldt_32
	;
	
	;
_code16		dd	?
_code32		dd	?
_code32_tss	dd	?
	;

	;
v86r_ax		label	near
v86r_al		db	?
v86r_ah		db	?
v86r_bx		label	near
v86r_bl		db	?
v86r_bh		db	?
v86r_cx		label	near
v86r_cl		db	?
v86r_ch		db	?
v86r_dx		label	near
v86r_dl		db	?
v86r_dh		db	?
v86r_si		dw	?
v86r_di		dw	?
v86r_bp		dw	?
v86r_ds		dw	?
v86r_es		dw	?
v86r_flags	dw	?
	;
	
	;
mon_tss	dd	0			; _back
	dd	stack_32_tss		; _stk0
	dd	data_tss_sel
	dq	0			; _stk1
	dq	0			; _stk2
	dd	0			; _cr3
	dd	begin_monitor		; _eip
	dd	0			; _eflag
	dd	0			; _eax
	dd	0			; _ecx
	dd	0			; _edx
	dd	0			; _ebx
	dd	stack_32_tss		; _esp
	dd	0			; _ebp
	dd	0			; _esi 
	dd	0			; _edi
	dd	data_tss_sel		; _es
	dd	code_tss_sel		; _cs
	dd	data_tss_sel		; _ss
	dd	data_tss_sel		; _ds
	dd	core_sel		; _fs
	dd	data_32_sel		; _gs
	dd	ldt_sel			; _ldt
	dw	0			; _dtb
	dw	$ + 2 - mon_tss		; bm_off i/o bitmap (bm)
	db	401h / 8 dup(0)		; the bm ;7/15 B0 chip
end_mon_tss	label	byte
	db	0ffh			; end_bm
	;
tmp_tss	dd	0			; _back
	dd	stack_32_tss		; _stk0
	dd	data_tss_sel
	dq	0			; _stk1
	dq	0			; _stk2
	dd	0			; _cr3
	dd	0			; _eip
	dd	0			; _eflag
	dd	0			; _eax
	dd	0			; _ecx
	dd	0			; _edx
	dd	0			; _ebx
	dd	0			; _esp
	dd	0			; _ebp
	dd	0			; _esi 
	dd	0			; _edi
	dd	0			; _es
	dd	0			; _cs
	dd	0			; _ss
	dd	0			; _ds
	dd	0			; _fs
	dd	0			; _gs
	dd	0			; _ldt
	dw	0			; _dtb
	dw	$ + 2 - tmp_tss		; _bm_off
	db	401h / 8 dup(0)		; the bm ;7/15 B0 chip
end_tmp_tss	label	near
	db	0ffh			; end_bm
	;
	
	;
orig_21h	db	?
orig_a1h	db	?
	;

	;
start_32:
	;
	mov ax, data_32_sel
	;
	mov ss, ax
	mov esp, offset stack_32_end
	;
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	;
	pushfd
	pop eax
	;
	or eax, ioplfl
	;
	push eax
	popfd
	;
	in al, 21h
	mov byte ptr [orig_21h], al
	;
	or al, 03h
	out 21h, al
	;
	in al, 0a1h
	mov byte ptr [orig_a1h], al
	;
	mov bx, 2820h
	call set_8529_vektorz
	;
	mov ax, tmp_tss_sel
	ltr ax
	;
	mov ax, ldt_sel
	lldt ax
	;
	sti
	;
	call do_something
	;
_exit_:
	;
	cli
	;
	mov ax, data_32_sel
	;
	mov ss, ax
	mov esp, offset stack_32_end
	;
	mov ds, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	;
	lea esi, [check_text]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	mov bx, 7008h
	call set_8529_vektorz
	;
	mov al, byte ptr [orig_21h]
	out 21h, al
	;
	mov al, byte ptr [orig_a1h]
	out 0a1h, al
	;
	mov eax, cr0
	and eax, not 80000000h
	mov cr0, eax
	;
	xor eax, eax
	mov cr3, eax
	;
	db	0eah
	dw	offset real_mode_entry, 0, code_16_sel
	;
	
	;
check_text	dw	0, 3
		db	01fh, 'Diz iz check_text ...', 0
	;

	;
do_something:
	;
	;db	0eah
	;dd	0
	;dw	tss_sel
	;
	lea esi, [_text_]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	mov word ptr [v86r_ax], 0
	mov al, 33h
	int 30h
	;
	mov word ptr [v86r_ax], 1
	mov al, 33h
	int 30h
	;
	mov word ptr [v86r_ax], 0
	mov al, 16h
	int 30h
	;
	mov word ptr [v86r_ax], 2
	mov al, 33h
	int 30h
	;
	mov word ptr [v86r_ax], 03h
	mov al, 10h
	int 30h
	;
	retn
	;
	
	;
_text_	dw	0, 0
	db	1fh, 'Tak a sem v protectu ...', 0
	;
	
	;
write_message:
	;
	push es
	;
	mov ax, core_sel
	mov es, ax
	;
	movzx edi, word ptr ds:[esi + 2]
	;
	imul edi, 160
	;
	add di, word ptr ds:[esi]
	add di, word ptr ds:[esi]
	;
	add edi, 0b8000h
	;
	mov ah, byte ptr ds:[esi + 4]
	;
	add esi, 5
	;
write_message_loop:
	;
	lodsb
	;
	or al, al
	jz write_message_end
	;
	stosw
	;
	jmp write_message_loop
	;
write_message_end:
	;
	pop es
	;
	retf
	;
	
	;
show_regz:
	;
	push es
	push ds
	;
	pushad
	;
	mov ebp, esp
	add dword ptr [ebp + 12], 10h
	;
	mov ax, data_32_sel
	mov es, ax
	mov ds, ax
	;
	lea esi, [regz]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	mov edi, 0b8000h + 22 * 160
	;
	sub edi, dword ptr es:[_code32]
	;
	lea ebx, [hex_table]
	;
	mov ah, 0ah
	;
	mov ebp, 8
	;
show_regz_loop:
	;
	pop edx
	;
	mov ecx, 8
	;
	call print_reg
	;
	dec ebp
	jnz show_regz_loop
	;
	db	0ebh
_jump_	db	00h
	;
	mov byte ptr [_jump_], show_regz_end - (_jump_ + 1)
	;
	lea esi, [_regz_]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	mov ah, 0ah
	;
	mov edi, 0b8000h + 24 * 160
	;
	sub edi, dword ptr es:[_code32]
	;
	mov ebp, esp
	;
	push gs
	push fs
	;
	push dword ptr [ebp]
	push dword ptr [ebp + 4]
	push dword ptr [ebp + 12]
	;
	push ss
	;
	push dword ptr [ebp + 8]
	;
	mov ebp, 7
	;
	jmp short show_regz_loop
	;

	;
show_regz_end:
	;
	pop ds
	pop es
	;
	retf
	;
print_reg:
	;
	rol edx, 4
	;
	mov al, dl
	;
	and al, 0fh
	;
	xlat
	;
	stosw
	;
	loop print_reg
	;
	mov al, ' '
	;
	stosw
	;
	stosw
	;
	ret	
	;
regz	dw	0, 21
	db	0ah, 'edi =     '
	db	'esi =     '
	db	'ebp =     '
	db	'esp =     '
	db	'ebx =     '
	db	'edx =     '
	db	'ecx =     '
	db	'eax =     ', 0
_regz_	dw	0, 023
	db	0ah, 'eip =     '
	db	'ss =      '
	db	'cs =      '
	db	'es =      '
	db	'ds =      '
	db	'fs =      '
	db	'gs =      ', 0
hex_table	db	'0123456789ABCDEF'
	;
	
	;
set_8529_vektorz:
; bl - low vektor base #
; bh - high vektor base #
	;
	mov al, 11h
	out 20h, al
	;
	jmp short $ + 2
	;
	mov al, bl
	out 21h, al
	;
	jmp short $ + 2
	;
	mov al, 04h
	out 21h, al
	;
	jmp short $ + 2
	;
	mov al, 01h
	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, 02h
	out 0a1h, al
	;
	jmp short $ + 2
	;
	mov al, 01h
	out 0a1h, al
	;
	jmp short $ + 2
	;
	mov al, 0ffh
	out 0a1h, al
	;
	retn
	;

	; Exception_&_irg_handlerz ...
	
	;
exception_0:
	;
	push ax
	xor al, al
	jmp zpracuj_irq_
	;
exception_1:
	;
	push ax
	mov al, 01h
	jmp zpracuj_irq_
	;
exception_2:
	;
	push ax
	mov al, 02h
	jmp zpracuj_irq_
	;
exception_3:
	;
	push ax
	mov al, 03h
	jmp zpracuj_irq_
	;
exception_4:
	;
	push ax
	mov al, 04h
	jmp zpracuj_irq_
	;
exception_5:
	;
	push ax
	mov al, 05h
	jmp zpracuj_irq_
	;
exception_6:
	;
	push ax
	mov dl, 06h
	jmp zpracuj_exception
	;
exception_7:
	;
	push ax
	mov al, 07h
	jmp zpracuj_irq_
	;
exception_8:
	;
	push ax
	mov dl, 08h
	jmp zpracuj_exception
	;
exception_9:
	;
	push ax
	mov dl, 09h
	jmp zpracuj_exception
	;
exception_a:
	;
	push ax
	mov dl, 0ah
	jmp zpracuj_exception
	;
exception_b:
	;
	push ax
	mov dl, 0bh
	jmp zpracuj_exception
	;
exception_c:
	;
	push ax
	mov dl, 0ch
	jmp zpracuj_exception
	;
exception_e:
	;
	push ax
	mov dl, 0eh
	jmp zpracuj_exception
	;
unexpected_exc:
	;
	push ax
	mov dl, 0ffh
	;
zpracuj_exception:
	;
	pop cx
	;
	pushad
	push ds
	;
	mov ax, data_32_sel
	mov ds, ax
	;
	lea esi, [exception_text]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	pop ds
	popad
	;
	db	09ah
	dd	0
	dw	regz_sel
	;
	jmp _exit_
	;
	
	;
exception_text	dw	0, 20
		db	0ah, 'An exception occured ...', 0
	;

	;	
vm8086_gen_prot:
	;
	test byte ptr [esp + 14], 02h
	jnz short vm8086_gen_prot_next
	;
	mov dl, 13
	;
	jmp zpracuj_exception
	;
vm8086_gen_prot_next:
	;
	add esp, 04h
	;
	pushad
	;
	mov ax, core_sel
	mov ds, ax
	;
	movzx ebx, word ptr [esp + 36]
	;
	shl ebx, 4
	add ebx, dword ptr [esp + 32]
	;
	inc word ptr [esp + 32]
	;
	mov al, byte ptr [ebx]
	;
	mov dl, 03h
	cmp al, 0cch
	je do_vm8086_int
	;
	mov dl, 13
	;
	jc zpracuj_exception
	;
	cmp al, 0ceh
	ja zpracuj_exception
	je ok_itz_into
	;
	inc word ptr [esp + 32]
	;
	mov dl, byte ptr [ebx+1]
	;
	cmp dl, 0fdh
	jne do_vm8086_int
	;
	jmp ret_from_vm8086_int
	;
ok_itz_into:
	;
	mov dl, 04h
	;
do_vm8086_int:
	;
	mov ax, core_sel
	mov ds, ax
	;
	movzx ebx, dl
	;
	shl ebx, 2
	;
	movzx edx, word ptr [esp + 48]
	;
	shl edx, 4
	;
	sub word ptr [esp + 44], 06h
	;
	add edx, dword ptr [esp + 44]
	;
	mov ax, word ptr [esp + 40]
	mov word ptr [edx + 4], ax
	;
	mov ax, word ptr [esp + 36]
	mov word ptr [edx + 2], ax
	;
	mov ax, word ptr [esp + 32]
	mov word ptr [edx], ax
	;
	and word ptr [esp + 40], 0fcffh
	;
	mov eax, dword ptr [ebx]
	mov word ptr [esp + 32], ax
	;
	shr eax, 16
	;
	mov word ptr [esp + 36], ax
	;
	popad
	;
	iretd
	;

	;
irq_0:
	;
	push ax
	mov al, 08h
	jmp zpracuj_irq_
	;
irq_1:
	;
	push ax
	mov al, 09h
	jmp zpracuj_irq_
	;
irq_2:
	;
	push ax
	mov al, 0ah
	jmp zpracuj_irq_
	;

irq_3:
	;
	push ax
	mov al, 0bh
	jmp zpracuj_irq_
	;

irq_4:
	;
	push ax
	mov al, 0ch
	jmp zpracuj_irq_
	;

irq_5:
	;
	push ax
	mov al, 0dh
	jmp zpracuj_irq_
	;

irq_6:
	;
	push ax
	mov al, 0eh
	jmp zpracuj_irq_
	;

irq_7:
	;
	push ax
	mov al, 0fh
	jmp zpracuj_irq_
	;

irq_8:
	;
	push ax
	mov al, 70h
	jmp zpracuj_irq_
	;

irq_9:
	;
	push ax
	mov al, 71h
	jmp zpracuj_irq_
	;

irq_a:
	;
	push ax
	mov al, 72h
	jmp zpracuj_irq_
	;

irq_b:
	;
	push ax
	mov al, 73h
	jmp zpracuj_irq_
	;

irq_c:
	;
	push ax
	mov al, 74h
	jmp zpracuj_irq_
	;

irq_d:
	;
	push ax
	mov al, 75h
	jmp zpracuj_irq_
	;

irq_e:
	;
	push ax
	mov al, 76h
	jmp zpracuj_irq_
	;

irq_f:
	;
	push ax
	mov al, 77h
	;
zpracuj_irq_:
	;
	test byte ptr [esp + 12], 02h
	jnz short itz_irq_from_vm8086
	;
	db	09ah
	dd	0
	dw	regz_sel
	;
	int 30h
	;
	pop ax
	;
	iretd
	;
itz_irq_from_vm8086:
	;
	push ax
	;
	mov ax, data_32_sel
	mov gs, ax
	;
	pop ax
	;
	mov byte ptr gs:[vm8086_irq_number], al
	;
	jmp $ + 2
	;
	pop ax
	;
	pushad
	;
	db	0b2h
vm8086_irq_number	db	?
	;
	jmp do_vm8086_int
	;
	
	;
vm8086_int:
	;
	pushad
	;
	push fs
	push gs
	push es
	push ds
	;
	push ax
	;
	mov ax, core_sel
	mov es, ax
	;
	mov ax, data_32_sel
	mov ds, ax
	;
	pop ax
	;
	mov ebx, dword ptr [_code16]
	mov byte ptr es:[ebx + vm8086_interrupt_number], al
	;
	mov dword ptr [mov_esp_?], esp
	mov word ptr [mov_ax_?], ss
	;
	xor eax, eax
	;
	push eax
	push eax
	;
	mov ax, word ptr [v86r_ds]
	push eax
	mov ax, word ptr [v86r_es]
	push eax
	;
	mov eax, code16
	push eax
	mov eax, offset stack_16_end
	push eax
	;
	pushfd
	pop eax
	;
	or eax, 20000h
	push eax
	;
	mov eax, code16
	push eax
	mov eax, offset vm_code
	push eax
	;
	iretd
	;
ret_from_vm8086_int:
	;
	db	66h, 0b8h
mov_ax_?	dw	?
	;
	mov ss, ax
	;
	db	0bch
mov_esp_?	dd	?
	;
	pop ds
	pop es
	pop gs
	pop fs
	;
	popad
	;
	iretd
	;

code32	ends

	; VM8086_monitor_seg
code32_tss	segment para public use32
		assume cs:code32_tss, ds:code32_tss
	;
	db	stack_32_tss_ dup(?)
stack_32_tss	label	near
	dd	dos_return			; eip
	dd	code16				; seg
	dw	ifl or ioplfl, vmfl		; eflagz
	dd	offset stack_16_end		; esp
	dd	code16				; ss
	dd	code16				; es
	dd	code16				; ds
	dd	0				; fs
	dd	0				; gs
	;

	;
vm_text	dw	0, 2
	db	01fh, 'Ted jsem v VM8086_monitoru ...', 0
	;

	;
begin_monitor:
	;
	lea esi, [vm_text]
	;
	db	09ah
	dd	0
	dw	gate_sel
	;
	iretd
	;
	
code32_tss	ends

last_segment	segment para public use16
last_segment	ends

	end	start_16