Unfortunately after starting debuggers aren't acting. An code emulating instruction int1 is needed. Whether somebody would help me to fix it.
; ============= 32-bit Extender for 16-bit DOS (v1.1) =============
; assemble using tasm
.seq
.386p
io_limit equ 2000h
stack16_size equ 80h
code segment public use32
assume cs:code
base_sel equ base_desc - GDT
code_sel equ code_desc - GDT
data_sel equ data_desc - GDT
code16_sel equ code16_desc - GDT
data16_sel equ data16_desc - GDT
env_sel equ env_desc - GDT
ext_sel equ ext_desc - GDT
flat_code_sel equ flat_code_desc - GDT
flat_data_sel equ flat_data_desc - GDT
psp_sel equ psp_desc - GDT
video_sel equ video_desc - GDT
public V86_es, V86_ds, V86_fs, V86_gs
align 4
V86_es dd code
V86_ds dd code
V86_fs dd 0
V86_gs dd 0a000h
V86_ss dd stack16
V86_sp dd stack16_size
TSS_esp0 dd (32+16)*8+4
public psp_segment, base_segment, base_limit
public ext_base, ext_limit, fpu_present
psp_segment dw ?
base_segment dw ?
base_limit dd ?
ext_base dd 100000h
ext_limit dd ?
fpu_present db 0
; ============= V86 interupt call =============
align 4
public int_16
int_16 proc near
pushfd
push gs fs ds es ebx eax
mov ax,data_sel
mov ds,ax
mov ax,flat_data_sel
mov fs,ax
mov eax,ds:TSS_esp0
push dword ptr fs:eax[4]
push dword ptr fs:eax[0]
mov fs:eax[0],esp
mov fs:eax[4],ss
push ds:V86_gs ds:V86_fs ds:V86_ds ds:V86_es
mov ebx,ds:V86_ss
push ebx
shl ebx,4
mov eax,ds:V86_sp
sub eax,6
push eax
add ebx,eax
mov word ptr fs:ebx[0],small offset int_?
mov word ptr fs:ebx[2],code
mov eax,ss:esp[14*4]
and ah,NOT 42h
push eax
popfd
mov fs:ebx[4],ax
or eax,23000h
push eax
mov ebx,ss:esp[17*4]
movzx eax,word ptr fs:ebx[2]
push eax
mov ax,word ptr fs:ebx[0]
push eax
mov eax,ss:esp[11*4]
mov ebx,ss:esp[12*4]
iretd
int_?:
int ?
int_16 endp
; ============= Virtual 8086 mode monitor =============
V86_monitor:
test byte ptr ss:esp[3*4+2],2
jz exc13
add esp,4
push ebx eax
mov ax,flat_data_sel
mov ds,ax
movzx ebx,word ptr ss:esp[3*4]
cmp bx,code
je V86_exit
shl ebx,4
add ebx,ss:esp[2*4]
inc dword ptr ss:esp[2*4]
mov ah,ds:ebx[0]
mov al,3
cmp ah,0cch
je short V86_int
inc eax
cmp ah,0ceh
je short V86_int
cmp ah,0cdh
jne short V86_exc
inc dword ptr ss:esp[2*4]
mov al,ds:ebx[1]
cmp al,15h
jne short V86_int
cmp byte ptr ss:esp[1],87h
je emul_15_87
; ------------- Emulate INT intruction -------------
V86_int:
push ecx
movzx ebx,al
shl ebx,2
mov ecx,ds:ebx[0]
movzx ebx,word ptr ss:esp[7*4]
shl ebx,4
sub word ptr ss:esp[6*4],6
add ebx,ss:esp[6*4]
mov ax,ss:esp[5*4]
mov ds:ebx[4],ax
and ah,NOT 3
mov ss:esp[5*4],ax
mov ax,ss:esp[4*4]
mov ds:ebx[2],ax
mov ax,ss:esp[3*4]
mov ds:ebx[0],ax
mov ss:esp[3*4],cx
shr ecx,16
mov ss:esp[4*4],cx
pop ecx eax ebx
iretd
V86_exc:
mov dx,offset err_v86_inv
jmp exception
; ------------- Leave V86 Interrupt call -------------
V86_exit:
mov ax,data_sel
mov ds,ax
pop eax ebx
mov ss:esp[11*4],eax
mov ss:esp[12*4],ebx
add esp,8
pop eax
mov ss:esp[14*4],al
pop ds:V86_sp ds:V86_ss
pop ds:V86_es ds:V86_ds ds:V86_fs ds:V86_gs
mov ax,flat_data_sel
mov ebx,ds:TSS_esp0
mov ds,ax
pop dword ptr ds:ebx[0]
pop dword ptr ds:ebx[4]
pop eax ebx es ds fs gs
popfd
ret 4
; ------------- Emulate 'MOVE BLOCK' BIOS call -------------
emul_15_87:
cmp ecx,8000h
ja short err_15_87
push edi esi ecx
movzx eax,word ptr ss:esp[10*4]
shl eax,4
movzx ebx,si
add eax,ebx
mov esi,ds:eax[10h + 7]
shl esi,24
mov ebx,ds:eax[10h + 2]
and ebx,0ffffffh
add esi,ebx
mov edi,ds:eax[18h + 7]
shl edi,24
mov ebx,ds:eax[18h + 2]
and ebx,0ffffffh
add edi,ebx
mov ax,ds
mov es,ax
cld
shr ecx,1
rep movsd
pop ecx esi edi
mov byte ptr ss:esp[1],0
and byte ptr ss:esp[4*4],NOT 1
jmp short exit_15_87
err_15_87:
mov byte ptr ss:esp[1],3
or byte ptr ss:esp[4*4],1
exit_15_87:
pop eax ebx
iretd
; ============= exception entries =============
exc0: mov dx,offset exc_0
jmp short exception
exc1: mov dx,offset exc_1
jmp short exception
exc2: mov dx,offset exc_2
jmp short exception
exc3: mov dx,offset exc_3
jmp short exception
exc4: mov dx,offset exc_4
jmp short exception
exc5: mov dx,offset exc_5
jmp short exception
exc6: mov dx,offset exc_6
jmp short exception
exc7: mov dx,offset exc_7
jmp short exception
exc8: mov dx,offset exc_8
jmp short exception
exc9: mov dx,offset exc_9
jmp short exception
exc10: mov dx,offset exc_10
jmp short exception
exc11: mov dx,offset exc_11
jmp short exception
exc12: mov dx,offset exc_12
jmp short exception
exc13: mov dx,offset exc_13
jmp short exception
exc14: mov dx,offset exc_14
jmp short exception
exc15: mov dx,offset exc_15
jmp short exception
exc16: mov dx,offset exc_16
jmp short exception
exc17: mov dx,offset exc_17
jmp short exception
exc18_31:
mov dx,offset exc_18_31
exception:
mov ebp,'EXCE'
; ! jmp code16_sel:exit16 !
db 0eah
dd exit16
dw code16_sel
; ============= Non Maskable Interrupt =============
NMI: call check_int
push 2*4
call int_16
iretd
; ============= Interrupt entries =============
int0: push offset irq0
jmp short check_int
int1: push offset irq1
jmp short check_int
int2: push offset irq2
jmp short check_int
int3: push offset irq3
jmp short check_int
int4: push offset irq4
jmp short check_int
int5: push offset irq5
jmp short check_int
int6: push offset irq6
jmp short check_int
int7: push offset irq7
jmp short check_int
int8: push offset irq8
jmp short check_int
int9: push offset irq9
jmp short check_int
int10: push offset irq10
jmp short check_int
int11: push offset irq11
jmp short check_int
int12: push offset irq12
jmp short check_int
int13: push offset irq13
jmp short check_int
int14: push offset irq14
jmp short check_int
int15: push offset irq15
check_int:
test byte ptr ss:esp[3*4+2],2
jz short not_V86
push eax
mov ax,data_sel
mov ds,ax
mov eax,ss:esp[5*4]
mov ds:V86_sp,eax
mov eax,ss:esp[6*4]
mov ds:V86_ss,eax
pop eax
mov es,ss:esp[14*4]
mov ds,ss:esp[15*4]
mov fs,ss:esp[16*4]
mov gs,ss:esp[17*4]
not_V86:
ret
code ends
; ============= Startup code =============
code16 segment use16
assume cs:code16
d32 proc
.8086
; ============= Check for 386 or above =============
push cs
pop ds
pushf
pushf
pop ax
xor ah,40h
push ax
popf
pushf
pop bx
popf
cmp ax,bx
je short NT_found
mov dx,offset err_no_386
jmp err_exit
NT_found:
.386p
; ============= Check for V86 mode =============
smsw ax
test al,1
jz short real_mode
mov dx,offset err_v86
jmp err_exit
real_mode:
; ============= Store environment and psp segments =============
movzx eax,word ptr es:[2ch]
shl eax,4
mov ds:env_desc[2],ax
shr eax,16
mov byte ptr ds:env_desc[4],al
mov ax,es
movzx ebx,word ptr es:[02h]
mov cx,code
mov es,cx
mov es:psp_segment,ax
shl eax,4
mov ds:psp_desc[2],ax
shr eax,16
mov byte ptr ds:psp_desc[4],al
; ============= Check for a Floating Point Unit =============
fninit
fnstsw ds:fp_status
cmp byte ptr ds:fp_status,0
jnz short no_fpu
fnstcw ds:fp_status
mov ax,ds:fp_status
and ax,103fh
cmp ax,3fh
jne short no_fpu
mov es:fpu_present,1
no_fpu:
; ============= Store code and code16 segments =============
mov ax,es
shl eax,4
sub ds:code_desc,ax
sub ds:data_desc,ax
mov ds:code_desc[2],ax
mov ds:data_desc[2],ax
shr eax,16
mov byte ptr ds:code_desc[4],al
mov byte ptr ds:data_desc[4],al
sub byte ptr ds:code_desc[6],al
sub byte ptr ds:data_desc[6],al
mov ax,cs
shl eax,4
add dword ptr ds:GDTR[2],eax
mov ds:code16_desc[2],ax
mov ds:data16_desc[2],ax
shr eax,16
mov byte ptr ds:code16_desc[4],al
mov byte ptr ds:data16_desc[4],al
; ============= Store free base segment =============
mov ax,stack16
add ds:IDT_seg,ax
add ax,(stack16_size + 48*8 + 68h + io_limit + 15)/16
sub bx,ax
ja short mem_ok
mov dx,offset err_mem
jmp err_exit
mem_ok:
mov es:base_segment,ax
shl eax,4
mov ds:base_desc[2],ax
shr eax,16
mov byte ptr ds:base_desc[4],al
shl ebx,4
mov es:base_limit,ebx
mov ds:base_desc,bx
shr ebx,16
mov byte ptr ds:base_desc[6],bl
; ============= Enable the A20 gate & Allocate extended memory ============
mov ax,4300h
int 2fh
cmp al,80h
jnz no_xms
; ------------- Enable through XMS driver -------------
push es
mov ax,4310h
int 2fh
mov word ptr ds:XMS_driver,bx
mov word ptr ds:XMS_driver[2],es
pop es
mov ah,05h
call ds:XMS_driver
cmp ax,1
jz short a20_XMS_enabled
mov dx,offset err_xms_a20
jmp err_exit
a20_XMS_enabled:
; ------------- Allocate through XMS driver -------------
mov ah,08h
call ds:XMS_driver
mov dx,ax
shl eax,10
mov es:ext_limit,eax
mov ah,09h
call ds:XMS_driver
cmp ax,1
je short alloc_ok
mov dx,offset err_xms_alloc
jmp err_exit
alloc_ok:
mov ds:XMS_handle,dx
mov ah,0ch
call ds:XMS_driver
cmp ax,1
je short lock_ok
mov dx,offset err_xms_lock
jmp err_exit
lock_ok:
mov ds:ext_desc[2],bx
mov byte ptr ds:ext_desc[4],dl
mov byte ptr ds:ext_desc[7],dh
mov word ptr es:ext_base,bx
mov word ptr es:ext_base[2],dx
mov ax,word ptr es:ext_limit
jmp ext_allocated
; ------------- Enable through 8042 (keyboard controller) -------------
wait_status_bit1 proc
xor cx,cx
wsb10: in al,64h
test al,2
jz short wsb11
loop wsb10
jmp short time_out
wsb11: ret
wait_status_bit1 endp
no_xms:
cli
mov al,0adh
out 64h,al
call wait_status_bit1
mov al,0d0h
out 64h,al
xor cx,cx
wsb00: in al,64h
test al,1
jnz short wsb01
loop wsb00
time_out:
mov dx,offset err_8042_a20
jmp err_exit
wsb01: in al,60h
push ax
mov al,0d1h
out 64h,al
call wait_status_bit1
pop ax
or al,2
out 60h,al
call wait_status_bit1
mov al,0aeh
out 64h,al
; ------------- Check if A20 really is enabled -------------
xor ax,ax
mov fs,ax
dec ax
mov gs,ax
mov al,fs:0
cmp al,gs:10h
jne short a20_8042_enabled
not al
mov fs:0,al
cmp al,gs:10h
not al
mov fs:0,al
jnz short a20_8042_enabled
mov dx,offset err_8042_a20
jmp err_exit
a20_8042_enabled:
; ------------- Get extended memory size (BIOS) -------------
mov ah,88h
int 15h
shl eax,10
mov es:ext_limit,eax
ext_allocated:
add eax,4095
shr eax,12
dec eax
mov ds:ext_desc,ax
shr eax,16
add byte ptr ds:ext_desc[6],al
; ============= Build IDT & TSS =============
push es
mov es,ds:IDT_seg
xor edi,edi
mov eax,code_sel * 65536 + offset exc0
mov ebx,8e00h
mov cx,19
loop1:
stosd
mov es:di[0],ebx
add di,4
add ax,small offset exc1 - exc0
loop loop1
mov word ptr es:di[-6*8],small offset V86_monitor
mov word ptr es:di[-17*8],small offset NMI
mov cx,13
loop2:
stosd
mov es:di[0],ebx
add di,4
loop loop2
mov ax,small offset int0
mov cx,16
loop3:
stosd
mov es:di[0],ebx
add ax,small offset int1 - int0
add di,4
loop loop3
xor eax,eax
mov cx,(68h + io_limit)/4
rep stosd
mov byte ptr es:di[0],-1
mov word ptr es:48*8 + 66h,68h
mov ax,es
shl eax,4
mov dword ptr ds:IDTR[2],eax
pop es
add es:TSS_esp0,eax
add ds:TSS_desc[2],ax
shr eax,16
mov byte ptr ds:TSS_desc[4],al
; ============= Set Programmable Interrupt Controller =============
cli
in al,21h
mov ds:irq_mask,al
in al,0a1h
mov ds:irq_mask[1],al
mov bx,2820h
call set_PIC
mov al,ds:irq_mask
out 21h,al
mov al,ds:irq_mask[1]
out 0a1h,al
; ============= Enter protected mode =============
lidt qword ptr ds:IDTR
lgdt qword ptr ds:GDTR
mov eax,CR0
or al,21h
mov CR0,eax
; ! jmp code16_sel:prot !
db 0eah
dw prot, code16_sel
; ============= Protected mode =============
prot:
mov ax,data_sel
mov es,ax
mov ds,ax
mov ss,ax
mov ax,flat_data_sel
mov fs,ax
mov ax,video_sel
mov gs,ax
mov esp,offset stack0
mov ax,TSS_desc - GDT
ltr ax
sti
; ! call code_sel:main !
db 66h, 67h, 09ah
dd offset main
dw code_sel
; ============= Leave protected mode =============
exit16:
cli
mov ax,data16_sel
mov es,ax
mov ds,ax
mov fs,ax
mov gs,ax
mov ss,ax
lidt ds:DOS_IDTR
mov eax,CR0
and al,NOT 21h
mov CR0,eax
; ! jmp code16:real !
db 0eah
dw real, code16
; ============= Real mode =============
real:
mov ax,0b800h
mov es,ax
mov ax,code16
mov ds,ax
mov ax,stack16
mov ss,ax
mov esp,offset stack16_size
; ============= Reset PIC =============
mov bx,7008h
call set_PIC
mov al,ds:irq_mask
out 21h,al
mov al,ds:irq_mask[1]
out 0a1h,al
mov al,20h
out 20h,al
out 0a0h,al
sti
; ============= Exception exit? =============
cmp ebp,'EXCE'
jne short exit
mov ah,0fh
int 10h
cmp al,7
je short mda
mov al,3
mda:
mov ah,0
int 10h
err_exit:
mov ah,9
int 21h
exit:
cmp word ptr ds:XMS_driver,0
je short no_xms_driver
mov ah,0dh
mov dx,ds:XMS_handle
call ds:XMS_driver
mov ah,0ah
call ds:XMS_driver
no_xms_driver:
mov ax,4c00h
int 21h
d32 endp
set_PIC proc
mov al,11h
out 20h,al
out 0a0h,al
mov al,bl
out 21h,al
mov al,bh
out 0a1h,al
mov al,4h
out 21h,al
mov al,2h
out 0a1h,al
mov al,1h
out 21h,al
out 0a1h,al
ret
set_PIC endp
; errors
err_8042_a20 db '8042 : Failed to enable A20 gate',10,36
err_no_386 db '80x86 : This program requires a i386 microprocessor',10,36
err_mem db 'Memory : Out of base memory',10,36
err_v86 db 'V86 : Already in protected mode',10,36
err_v86_inv db 'V86 : Invalid OP-Code',10,36
err_xms_a20 db 'XMS : Failed to enable A20 gate',10,36
err_xms_alloc db 'XMS : Failed to allocate XMS memory',10,36
err_xms_lock db 'XMS : Failed to lock XMS memory',10,36
; exceptions
exc_0 db '0 : Divide Error',10,36
exc_1 db '1 : Debug Exception',10,36
exc_2 db '2 : NMI Interrupt',10,36
exc_3 db '3 : One Byte Interrupt',10,36
exc_4 db '4 : Interrupt on Overflow',10,36
exc_5 db '5 : Array Bounds Check',10,36
exc_6 db '6 : Invalid OP-Code',10,36
exc_7 db '7 : Device Not Available',10,36
exc_8 db '8 : Double fault',10,36
exc_9 db '9 : Coprocessor Segment Overrun',10,36
exc_10 db '10 : Invalid TSS',10,36
exc_11 db '11 : Segment Not Present',10,36
exc_12 db '12 : Stack Fault',10,36
exc_13 db '13 : General Protection Fault',10,36
exc_14 db '14 : Page Fault',10,36
exc_15 db '15 : Reserved',10,36
exc_16 db '16 : Floating Point Error',10,36
exc_17 db '17 : Alignment Check Interrupt',10,36
exc_18_31 db '18-31 : Reserved',10,36
align 4
irq_mask db 0, 0
fp_status dw -1
IDT_seg dw stack16_size/16
XMS_driver dd 0
XMS_handle dw 0
align 8
GDT dd 0, 0
base_desc dw ?
dw ?
db ?
db 92h, ?, 0
code_desc dw 0ffffh
dw ?
db ?
db 9ah, 49h, 0
data_desc dw 0ffffh
dw ?
db ?
db 92h, 09h, 0
code16_desc dw 0ffffh
dw ?
db ?
db 9ah, 0, 0
data16_desc dw 0ffffh
dw ?
db ?
db 92h, 0, 0
env_desc dw 003ffh
dw ?
db ?
db 92h, 0, 0
ext_desc dw 00000h
dw 0
db 10h
db 92h, 080h, 0
flat_code_desc dw 0ffffh
dw 0
db 0
db 9ah, 08fh, 0
flat_data_desc dw 0ffffh
dw 0
db 0
db 92h, 08fh, 0
psp_desc dw 000ffh
dw ?
db ?
db 92h, 0, 0
video_desc dw 0ffffh
dw 0
db 0ah
db 92h, 01h, 0
TSS_desc dw 68h + io_limit
dw 180h
db ?
db 89h, 0, 0
GDTR dw $ - GDT
dd offset GDT
dw 0
IDTR dq 17fh
DOS_IDTR dq 3ffh
code16 ends
code segment public use32
assume cs:code
int16 macro n
push n*4
call int_16
endm
ComSpec db 'COMSPEC='
ParmBlock dw ?, 80h, ?, 5ch, ?, 6ch, ?
main proc far
mov ah,9 ; Write 1st message
mov dx,small offset mes1
int16 21h
mov ax,psp_sel ; Build Parameter Block
mov es,ax
mov cx,es:[2ch]
mov ds:ParmBlock[0],cx
mov ax,ds:psp_segment
mov ds:ParmBlock[4],ax
mov ds:ParmBlock[8],ax
mov ds:ParmBlock[12],ax
mov word ptr ds:V86_es,ax
mov bx,ds:base_segment
sub bx,ax
mov ah,4ah
int16 21h
jc short exitx
mov ax,env_sel ; Get COMSPEC environment variable
mov es,ax
xor eax,eax
xor edi,edi
m0:
mov esi,offset ComSpec
cmpsd
jne short m1
cmpsd
je short m2
m1:
scasb
jne short m1
jmp short m0
m2:
mov ax,4b00h ; Execute 'COMSPEC'
mov bx,small offset ParmBlock
mov dx,di
mov word ptr ds:V86_ds,cx
mov ds:V86_es,code
int16 21h
mov ah,9 ; Write 2nd message
mov dx,small offset mes2
mov ds:V86_ds,code
int16 21h
exitx:
ret ; End program
mes1 db 'Now in V86 mode',10,36
mes2 db 'Back in Real mode',10,36
main endp
irq0: inc dword ptr fs:0A0000h ; fs = value before INT16 call,
inc dword ptr fs:0B0000h ; and is flat_sel at startup
inc dword ptr fs:0B8000h
int16 08h
iretd
irq1: int16 09h
iretd
irq2: int16 0ah
iretd
irq3: int16 0bh
iretd
irq4: int16 0ch
iretd
irq5: int16 0dh
iretd
irq6: int16 0eh
iretd
irq7: int16 0fh
iretd
irq8: int16 70h
iretd
irq9: int16 71h
iretd
irq10: int16 72h
iretd
irq11: int16 73h
iretd
irq12: int16 74h
iretd
irq13: int16 75h
iretd
irq14: int16 76h
iretd
irq15: int16 77h
iretd
align 4
db 200h dup(0)
stack0 label
code ends
stack16 segment stack use16
db stack16_size dup (?)
stack16 ends
end d32