; 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 tss_des descriptor tmp_tss_des descriptor ldt_des descriptor regz_des descriptor ; gdt_length = ($ - offset gdt_32) - 1 ; ; _idt_ dw idt_length, small offset idt_32, 0 ; idt_32 descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor 17 dup() descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor descriptor ; 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