home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Unsorted BBS Collection
/
thegreatunsorted.tar
/
thegreatunsorted
/
programming
/
misc_programming
/
dos32.asm
< prev
next >
Wrap
Assembly Source File
|
1993-10-04
|
46KB
|
1,692 lines
COMMENT $
DOS32 Version 0.1
A 32 bit MSDOS extender for assembly programmers
supporting
Dos Protected Mode Interrupt Specification
and
System BIOS extended memory copy service (INT 15h AH = 87h)
for without DPMI.
Written by Adam Seychell SEP-1993
email s921880@minyos.xx.rmit.oz.au
$
.386p ; Enable "REAL" CPU instuctions.
Normal_stack equ 200h ; Size of your protected mode stack
V86_stack_size equ 200h ; Size of stack for V86 interrupt calls
PIC_Base equ 80h ; Base interrupt address for the 8259s
Data_sruct struc
C_EDI dd 0
C_ESI dd 0
C_EBP dd 0
C_resrved dd 0
C_EBX dd 0
C_EDX dd 0
C_ECX dd 0
C_EAX dd 0
C_FLAGS dw 0
C_ES dw 0
C_DS dw 0
C_FS dw 0
C_GS dw 0
C_IP dw 0
C_CS dw 0
C_SP dw 0
C_SS dw 0
ends
RealData struc
Real_GS dd 0
Real_FS dd 0
Real_DS dd 0
Real_ES dd 0
Real_SS dd 0
Real_ESP dd 0
tmp_Real_intNum db 0
ends
DATA32 SEGMENT PUBLIC 'DATA' USE32
global CODE32_sel :word
global CODE16_sel :word
global DATA_sel :word
global TheSTACK_sel :word
global VIDEO_sel :word
global FLAT_DATA_sel :word
global FLAT_CODE32_sel :word
global XMS_sel :word
global BASE_sel :word
global PSP_sel :word
global xms_usage :dword
global xms_base :dword
global Base_Segment :word
global PSP_segment :word
ENDS
global START32 :near
global IRQ0 :near
global IRQ1 :near
global IRQ2 :near
global IRQ3 :near
global IRQ4 :near
global IRQ5 :near
global IRQ6 :near
global IRQ7 :near
global IRQ8 :near
global IRQ9 :near
global IRQ10 :near
global IRQ11 :near
global IRQ12 :near
global IRQ13 :near
global IRQ14 :near
global IRQ15 :near
DATA32 SEGMENT PUBLIC 'DATA' USE32
DOS_CODE_sel dw DOS_CODE_Desc - GDT
DOS_DATA_sel dw DOS_DATA_Desc - GDT
tss_Level0ESP dd 0
V86_Lv0_StkSave dd 10h dup (0) ; TSS level 0 ESP save for V86 calls.
IDT_base dd 0
_tmp0_ dd 0
_tmp1_ dd 0
tmp_Real_Flags dd 0
V86_irq_Count db 0
DATA32 ENDS
CODE16 SEGMENT PUBLIC 'CODE' USE16
CODE16 ends
DATA16 SEGMENT PUBLIC 'DATA' USE16
DATA16 ends
CODE32 SEGMENT PUBLIC 'CODE' USE32
assume DS:DATA32 , CS:CODE32 , es:DATA32
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
Setup_Pmode: ; first 32bit protected mode point
sti
db 0eah ; jump to start of main program
dd offset start32 , code32_desc - gdt
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;************** EXCEPTION HANDLERS ... *********************
Exception:
mov ax,DATA_Desc - GDT
mov ds,ax
mov es,Flat_data_sel
mov ss,TheStack_sel
mov fs,FLAT_data_sel
mov gs,FLAT_data_sel
mov esp,100h
mov dx,offset unknown_int_exit_mesg
mov ebp,'ERRA' ; Exit with error code
int 21h
getexeec macro n
_386exception_&n&:
mov dx,offset e_&n
jmp All_exceptions
endm
x=0
rept 16
getexeec %x
x=x+1
endm
;═══════════════════════════════════════════════════════════════════════════
All_exceptions:
mov esp,100h
; jmp _Pmode_exit_error
;∙·∙·∙·∙·∙·∙·∙·∙∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
_Pmode_exit_error:
mov ax,TheSTACK_Desc - GDT
mov ss,ax
mov ebp,'ERRA'
int 21h ; Exit with error
set1STirqm macro nt
firstIRQ&nt:
push offset irq&nt
jmp check_HardwareINT
endm
x = 0
rept 16
set1STirqm %x
x=x+1
endm
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;═══════════════════════════════════════════════════════════════════════════
check_HardwareINT proc near
test dword ptr [esp+3*4],020000h
jz not_v86_irq ; jump if IRQ was from P.mode
push eax ; IRQ was from V86 mode.
mov eax,[esp+5*4] ; Put new V86 stack pointer
mov SS:[real_ESP],eax
mov eax,[esp+6*4] ; Put new V86 stack segment
mov SS:[real_SS],eax ; we Don't care about ES,DS,FS & GS
pop eax
mov fs,[esp+10*4] ; return segment reg selectors
mov ds,[esp+11*4] ; as they were before entering V86
mov gs,[esp+12*4]
mov es,[esp+13*4]
not_v86_irq:
ret ; Go to IRQ handler
endp
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;═══════════════════════════════════════════════════════════════════════════
;------- The General Exception Handler ---------------
;═══════════════════════════════════════════════════════════════════════════
General_Exeption_Handler:
test dword ptr [esp+4*3],0020000h ; Test VM bit
jnz V86_Monitor
mov dx,offset e_13
jmp All_Exceptions
;*****************************************
;********* Virtual 8086 exception handler *********
;*****************************************
V86_Monitor proc
add esp,4 ; delete the undocumented pushed error code
pushad
mov ax,Flat_DATA_Desc - GDT
mov fs,ax
;;; Find what instruction caused the exception ;;;;
movzx ebx,word ptr [esp+36] ; Get CS from stack
shl ebx,4
add ebx,[esp+32] ; Get EIP form stack
inc dword ptr [esp+32]
mov dl,fs:[ebx] ; Get opcode
mov al,3
cmp dl,0cch ; see if INT 3 Breakpoint
je short DO_v86int ; if so do it's int
mov al,4
cmp dl,0ceh ; See if INTO
je short Do_v86int ; if so do it's int
cmp dl,0cdh ; see if INT n
jne V86exc ; if not then exception
inc dword ptr [esp+32] ; It must be a INT n instruction
mov al,fs:[ebx+1] ; get INT n number
cmp al,0FFh ; If int 0ffh and Then
jz Exit_V86 ; return to main Program
cmp al,15h
jnz NoXmsToCopy
cmp byte ptr ss:[esp+7*4+1],87h ; Detect if v86 application
jz Emulate_XMS_COPY ; wants to copy extended mem
; i.e ah = 87h
NoXmsToCopy:
;****; Emulate V86 interrupt ;****;
DO_v86int: ; Do interrupt "AL" for V86 task
movzx ebx,al
shl ebx,2 ; Get 8086 Int Vector
movzx edx,word ptr [esp+(8+4)*4] ; Get SS stored on stack
shl edx,4
sub word ptr [esp+(8+3)*4],6 ; Sub ESP stored on stack by 6
add edx,[esp+(8+3)*4] ; edx = Phyical Address of V86 stack
mov ax,[esp+(8+2)*4] ;Put FLAGS from Prev.0 Stack to V86 stack
mov fs:[edx+4],ax
mov ax,[esp+(8+1)*4] ;Put CS from Prev.0 Stack to V86 stack
mov fs:[edx+2],ax
mov ax,[esp+(8+0)*4] ;Put IP from Prev.0 Stack to V86 stack
mov fs:[edx],ax
mov eax,fs:[ebx] ; Get real mode int vector (CS:IP)
mov [esp+(8+0)*4],ax ; Store it on prev. 0 Stack
shr eax,16
mov [esp+(8+1)*4],ax
ret86: and word ptr [esp+(8+2)*4],0fcffh
popad ; Clear DF & IF flags on prev. 0 Stack
iretd ; Return to V86 mode
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
Exit_V86:
mov ax,DATA_Desc - GDT
mov ds,ax
popad
mov [_tmp0_],eax
mov [_tmp1_],ebx
add esp,8 ; ignore EIP & CS
pop word ptr [esp+12*4+2] ; Get V86 EFLAGS onto
add esp,2 ; stack from the int 20h
pop ss:[Real_ESP]
pop ss:[Real_SS]
pop ss:[Real_ES]
pop ss:[Real_DS]
pop ss:[Real_FS]
pop ss:[Real_GS]
;Must return the TSS Level 0 ESP to the previous V86 call's Level 0 ESP value.
movzx eax,V86_irq_Count
sub al,1
jle jH98_V86 ; Only do it if a V86 call inside a call.
dec V86_irq_Count
dec eax
mov eax,[V86_Lv0_StkSave+EAX*4] ; Get previous TSS Lv0 ESP
mov ebx,[tss_Level0ESP] ; Get address of TSS Lv0 ESP
mov fs:[ebx],eax ; Load it.
jH98_V86:
mov eax,[_tmp0_] ;Return temperaly saved registers
mov ebx,[_tmp1_]
pop fs ds ; pop seg reg from the entering V86
pop gs es ; call; see My_EmulateRealInterupt proc
iretd ; Return to main program
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;═══════════════════════════════════════════════════════════════════════════
; Emulate the SYSTEM BIOS - COPY EXTENDED MEMORY Srevice for V86 application
; INT 15 & AH = 87h
;═══════════════════════════════════════════════════════════════════════════
COMMENT $
NOTE.
There is a problem with the BIOS int 15h ah = 87 emulation
when HIMEM.SYS calls it to transfer a XMS block while MSDOS is loaded
in the Upper Memeory Block. It seems to be called with the location
of the GDT ( for int 15 ah=87 ) in the ROM area. This gives an invalid GDT.
When DOS is loaded into convention memory everything work fine because
HIMEM.SYS returns a valid GDT on this call.
$
Emulate_XMS_COPY: ; A20 gate always seems to be on ?
; mov ax,DATA_Desc - GDT
; mov ds,ax
mov ecx,ss:[esp+(6)*4] ; Get Number of words to copy
and ecx,0ffffh
cmp cx,8000h
ja _error_1587
shr ecx,1
xor eax,eax
mov ax,ss:[esp+(8+5)*4] ; Get ES
shl eax,4
add ax,ss:[esp+(1)*4] ; Get SI
adc eax,0 ; EAX has location of GDT
mov ebx,eax
; sub ebx,0f0000h
; cmp ebx,010000h
; ja _error_1587
; push eax
mov esi,fs:[eax+7h+10h]
shl esi,24
mov edx,fs:[eax+2h+10h] ; Get 32bit Source address
and edx,0ffffffh
add esi,edx
mov edi,fs:[eax+7h+18h]
shl edi,24
mov edx,fs:[eax+2h+18h] ; Get 32bit Destination address
and edx,0ffffffh
add edi,edx
; write 'Source ',12
; mov edx,esi
; call hex_dword
; write ' Destination ',12
; mov edx,edi
; call hex_dword
; write ' Cout ',12
; mov edx,ecx
; shl edx,2
; call hex_dword
; write ' GDT ',12
; pop edx
; call hex_dword
; write ' CS:EIP ',10
; movzx edx,word ptr [esp+36] ; Get CS from stack
; shl edx,4
; add edx,[esp+32] ; Get EIP form stack
; call hex_dword
;
; write 'int 15 vect',11
; movzx edx,word ptr fs:[15h*4+2]
; shl edx,4
; add dx,fs:[15h*4]
; adc edx,0
; call hex_dword
; writeln
push fs
pop es
cld
rep movs dword ptr es:[edi],es:[esi] ; do the transfer
mov byte ptr [esp+(7*4)+1],00 ;return AH = 0
and byte ptr [esp+(8+2)*4],NOT 01 ; Clear Carry flag on prev. 0 Stack
jmp ret86
_error_1587:
or byte ptr [esp+(8+2)*4],01 ; Set Carry flag on prev. 0 Stack
mov byte ptr [esp+(7*4)+1],03 ;return AH
jmp ret86
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;═══════════════════════════════════════════════════════════════════════════
V86exc:
mov dx,offset _V86_illigal_err
jmp _Pmode_exit_error
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
endp
;**********************************
MyDPMI_services:;*********************
;**********************************
cmp ax,0205h
jz SetPmodeintVector
cmp ax,0204h
jz GetPmodeintVector
cmp ax,0400h
jz GetVersion
iretd
SetPmodeintVector:
push edi ebx fs ds
mov ax,data_desc - gdt
mov ds,ax
mov fs,[flat_DATA_sel]
movzx ebx,bl
mov edi,ebx
sub edi,Pic_Base ; No allowed to set the hardware int vectors
cmp edi,15
jbe Set_irq_vec
mov edi,[idt_base]
mov fs:[ebx*8+edi],dx ; offset 0..15
SHR EDX,16
mov fs:[ebx*8+edi+6],dx ; offset 16..32
mov fs:[ebx*8+edi+2],cx ; Code Selector
pop ds fs ebx edi
iretd
GetPmodeintVector:
push edi ebx fs ds
mov ax,data_desc - gdt
mov ds,ax
mov fs,[flat_DATA_sel]
movzx ebx,bl
shl ebx,3
add ebx,[idt_base]
mov edi,[idt_base]
mov dx,fs:[ebx+6] ; Get offset 16..32
SHL EDX,16
mov dx,fs:[ebx] ; Get offset 0..15
mov cx,fs:[ebx+2] ; Get Code Selector
ivec22: pop ds fs ebx edi
iretd
Set_irq_vec:
stc
jmp ivec22
GetVersion: ; Emulate DPMI service Get Version
; only need to emulate the returned values of PIC bases
mov dh,PIC_base
mov dl,PIC_base+8
iretd
;═══════════════════════════════════════════════════════════════════════════
; PROCEDURE TO EMULATE REAL MODE INTERRUPT
;
;═══════════════════════════════════════════════════════════════════════════
DPMI_EmulateRealInterupt proc far
push ax
push 0 0 0
push word ptr ss:[Real_DS]
push word ptr ss:[Real_ES]
push word ptr [esp+18+8]
pushad
mov edi,esp
push es
push ss
pop es
mov ax,0300h
mov bl,ss:[tmp_Real_intNum]
xor ecx,ecx
int 31h ; Use the DPMI service
pop es
popad
pop word ptr [esp+26] ; return eflags
pop word ptr ss:[Real_ES]
pop word ptr ss:[Real_DS]
add esp,14
iretd
ENDP
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
My_EmulateRealInterupt proc far
push es gs ds fs ; save segment registers.
push eax
mov ax,data_desc - gdt ; Load seg regs.
mov ds,ax
mov fs,[flat_data_sel]
pop _tmp0_ ; temperly save eax.
mov eax,[esp+4*6] ; Get flags from stack.
mov [tmp_Real_Flags],eax ; Temperaly saved them.
mov eax,[tss_Level0esp] ; Set Level 0 stack to current ESP
mov fs:[eax],esp
movzx eax,V86_irq_Count
mov [V86_Lv0_StkSave+EAX*4], ESP
inc V86_irq_Count
pushfd ; Clear Nested Task, ( bit 14 )
pop eax ; If set then the 386 will
and ah,10111111b ; use the back link field in the TSS
push eax ; to switch tasks. A no no.
popfd
mov eax,seg V86IntNumber
shl eax,4
push ebx ; Load the V86 interrupt number
mov bl,SS:[tmp_Real_intNum] ; get it
mov byte ptr fs:[offset V86IntNumber+1+EAX],BL ; put it
pop ebx
push SS:[Real_GS] ; GS
push SS:[Real_FS] ; FS
push SS:[Real_DS] ; DS
push SS:[Real_ES] ; ES
push SS:[Real_SS] ; SS
push SS:[Real_ESP] ; ESP
mov eax,00023000h ; IOPL = 3 , VM = 1
or ax,word ptr [tmp_Real_Flags]
push eax ; EFLAGS
mov eax,seg TASK0_V86
push eax ; CS
mov eax,offset TASK0_V86
push eax ; EIP
mov eax,_tmp0_ ; Return origonal EAX value
IRETD ; Enter V86 mode !!!!!
endp
;¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡¡
TASK0_V86:
V86IntNumber: int 000h
int 0ffh ; exit V86 mode
CODE32 ENDS
DOS_CODE SEGMENT PUBLIC 'CODE' USE16
assume CS:dos_CODE , DS:DOS_CODE , fs:data32
;
; Format of a 386DX TSS (Task State Segment)
;
tss struc
tss_prev dw 0 ,0 ; back link to previous TSS
tss_esp0 dd 0 ; Priv. 0 ESP
tss_ss0 dw 0 ; Priv. 0 SS
dw 0 ; unused
tss_esp1 dd 0 ; Priv. 1 ESP
tss_ss1 dw 0 ; Priv. 1 SS
dw 0 ; unused
tss_esp2 dd 0 ; Priv. 2 ESP
tss_ss2 dw 0 ; Priv. 2 SS
dw 0 ; unused
tss_cr3 dd 0 ; PDBR
tss_eip dd 0
tss_eflags dd 0
tss_eax dd 0
tss_ecx dd 0
tss_edx dd 0
tss_ebx dd 0
tss_esp dd 0
tss_ebp dd 0
tss_esi dd 0
tss_edi dd 0
tss_es dw 0,0
tss_cs dw 0,0
tss_ss dw 0,0
tss_ds dw 0,0
tss_fs dw 0,0
tss_gs dw 0,0
tss_ldt dw 0,0
tss_t dw 0 ; if bit 0 set, exception on tsk switch
tss_iobase dw 068h ; points to beg. of I/O permissions map
tss_iomap db 2000h dup (0) ; I/O permissions bit map
tss_ioend db 11111111b ; I/O map trailer
TSS_ENDS equ $
tss ends
s_ACCESS record d_P:1,d_DPL:2,s_S:1,d_TYPE:4
s_INFO record d_G:1,d_D:1,d_nul:1,d_avl:1,d_lim:4
align 8
GDT dd 0,0 ; First descriptor is always NULL.
; Data DESCRIPTOR for a FLAT memory model
Flat_Data_Desc dw 0ffffh ; Limit[15..0]
db 0,0,0 ; Base[23..0]
s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <1,1,0,0,0fh> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Code DESCRIPTOR for a FLAT memory model
Flat_Code32_Desc dw 0ffffh ; Limit[15..0]
db 0,0,0 ; Base[23..0]
s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
s_INFO <1,1,0,0,0fh> ; G,D,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Data DESCRIPTOR for the free extented memory block
XMS_Desc dw 0000h ; Limit[15..0]
db 00,00,10h ; Base[23..0]
s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <1,0,0,0,00h> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Data DESCRIPTOR with base = start of free base memory
BASE_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,0,0,0,0fh> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Data DESCRIPTOR with base = 0A0000h
Video_Desc dw 0ffffh ; Limit[15..0]
db 00,00,0Ah ; Base[23..0]
s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,0,0,0,01h> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Data DESCRIPTOR for the STACK
TheSTACK_Desc dw Normal_stack-1 ; Limit[15..0]
db 00,00,00h ; Base[23..0]
s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,1,0,0,00h> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; 16bit data and code DESCRIPTORS for real mode ( DOS )
DOS_Code_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
s_INFO <0,0,0,0,00h> ; G,D,0,avl,Limit[19..16]
db 0 ; Base[31..24]
Dos_Data_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,0,0,0,0h> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; Data PSP Descr with base = PSP , limit = 100h
PSP_desc dw 0ffh ; Limit[15..0]
db 00,00,00h ; Base[23..0]
s_ACCESS <1,00,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,0,0,0,00h> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
; DATA and CODE DESCRIPTORS for your dos extender
Code32_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
s_INFO <0,1,0,0,0fh> ; G,D,0,avl,Limit[19..16]
db 0 ; Base[31..24]
Code16_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,1,1010b> ; P,DPL,1,type[E=1,C,R,A ]
s_INFO <0,0,0,0,0fh> ; G,D,0,avl,Limit[19..16]
db 0 ; Base[31..24]
Data_Desc dw 0ffffh ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00b,1,0010b> ; P,DPL,1,type[E=0,ED,W,A ]
s_INFO <0,0,0,0,0fh> ; G,B,0,avl,Limit[19..16]
db 0 ; Base[31..24]
MyMain_TSS_Desc dw TSS_ends ; Limit[15..0]
db ?,?,? ; Base[23..0]
s_ACCESS <1,00,0,09h> ; P,DPL,0,(type = avalible 386 TSS )
s_INFO <0,0,0,0,00h> ; G,0,0,0,Limit[19..16]
db 0 ; Base[31..24]
GDT_ends equ $ - GDT
;======== ERROR MESSAGES FOR PROGRAM TERMINATION IN NON-DPMI ===============
unknown_int_exit_mesg db 'Exited from Unhandled protected mode interrupt',10,13,36
_V86_illigal_err db 10,13,' Invalid Instuction in V86 mode ',10,13,36
_exit_errror db 10,10,' PROGRAM TERMINATED ',10,13,7,36
e_0 db '0 Divide error',10,13,36
e_1 db '1 Debug exception',10,13,36
e_2 db '2 Non-Maskable interrupt',10,13,36
e_3 db '3 Breakpoint',10,13,36
e_4 db '4 Overflow',10,13,36
e_5 db '5 Range Exceeded',10,13,36
e_6 db '6 Invalid opcode',10,13,36
e_7 db '7 No math unit avalible',10,13,36
e_8 db '8 Reserved',10,13,36
e_9 db '9 Reserved',10,13,36
e_10 db '10 Invalid TSS',10,13,36
e_11 db '11 Segment Not Present',10,13,36
e_12 db '12 Stack exception',10,13,36
e_13 db '13 General Protection Exception',10,13,36
e_14 db '14 Page fault',10,13,36
e_15 db '14 Reserved',10,13,36
DOS_IDT_value dw 03ffh,0,0,0
DPMI_entry dw 0,0
xms_usage_tmp dd 0
_tmpL_xms_base dw 0
_tmpH_xms_base dw 0
xms_driver dd 0
XMS_handle dw 0,0
oirqMask db 0,0
DPMI_Selector dw 0
PIC1_Base db 0
PIC2_Base db 0
;----------------------------------------------------------------------------
;───────────────────── INTERNAL ROUTINES ───────────────────────────────────
;----------------------------------------------------------------------------
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
free_XMS_memory proc near
cmp [xms_driver],0
jz No_xms_driver
; UNLOCK THE ALLOCATED EXTENDED MEMORY BLOCK
mov ah,0Dh
mov dx,[XMS_handle]
call [XMS_Driver]
; FREE ALLOCATED BLOCK
MOV AH,0Ah
mov dx,[XMS_handle]
call [xms_driver]
No_xms_driver: RET
free_XMS_memory endp
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;─────────────────────────────────────────────────────────────────────────────
; Set new IRQ vector numbers
set_8259intvec proc ; Set IRQ vectors 0..7 to bl
; and IRQ vectors 8..15 to bh
CLI ;∙·∙·∙·∙·∙·∙· set first 8259A PIC ∙·∙·∙·∙·∙·∙·
mov al,00010001b ;ICW1
out 20h,al ;icw4 is needed
call Delay8259
mov al,bl ;ICW2
out 21h,al ;( Set PIC 1 Base interrupt number )
call Delay8259
mov al,4h ;ICW3
out 21h,al
call Delay8259
mov al,1h ;ICW4
out 21h,al
call Delay8259 ;∙·∙·∙·∙·∙·∙· set second 8259A PIC ∙·∙·∙·∙·∙·∙·
mov al,00010001b ;ICW1
out 0a0h,al ;icw4 is needed
call Delay8259
mov al,bh ;ICW2
out 0a1h,al ;( Set PIC 2 Base interrupt number )
call Delay8259
mov al,00000010b ;ICW3
out 0a1h,al
call Delay8259
mov al,0000001b ;ICW4
out 0a1h,al
call Delay8259
ret
delay8259: mov ax,1000h
@3del: dec ax
jnz @3del
ret
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
;─────────────────────────────────────────────────────────────────────────────
endp
Go_REAL_MODE proc near
;─────────────────────────────────────────────────────────────────────────────
; Entry point to exit proteceded mode and restore hardware configeration.
; Then exits back to MSDOS. ( only for non-DPMI )
;─────────────────────────────────────────────────────────────────────────────
cli
mov al,00110100b ; SLOW DOWN TIMER
out 43h,al
XOR AL,AL
out 40h,al
out 40h,al
; Exit protected mode and return to DOS
; Load Data registers with 8086 SEGMENTs
mov ax,DOS_Data_Desc - GDT
mov ss,ax
mov es,ax
mov ds,ax
mov fs,ax
mov gs,ax
cli
lidt qword ptr DOS_IDT_value ; Set IDT to how DOS want's it
; Exit protecded mode
mov eax,CR0
and al,NOT 1 ;Clear PE bit
mov CR0,eax
db 0eah
dw To_MSDOS , Dos_CODE ; reload CS:IP
To_MSDOS: ;-- remap IRQ int vectors ---
mov bl,008h
mov bh,070h
call set_8259intvec
assume ds:dos_code
mov ax,dos_code
mov ds,ax
mov ax,TheStack ; Set up a bit of stack just to exit
mov ss,ax
mov esp,100h
mov al,oirqMask ; return origonal values of the IRQ mask bits
out 21h,al
mov al,oirqMask+1
out 0A1h,al
mov al,20h
out 20h,al
out 0a0h,al
in al,60h
cmp ebp,'ERRA'
jnz normal_terminate
; Print error message if need to
mov ah,9
int 21h
mov dx,offset _exit_errror
int 21h
normal_terminate:
call free_XMS_memory ; deallocated XMS
Exit_To_MSDOS:
mov ax,4C00h
int 21h
assume ds:dos_code
endp
;---------------- finished exiting routine -------------------------
COMMENT $
All data below this point of this segment is not needed after initalization.
Thus it can be (next Version) over witten after all the setting up is done.
This saves a bytes. See the 32bit setup code at "Setup_Pmode:" above.
>->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->
$
align 16
NON_DPMI_initalize_start:
GDTR_value dw GDT_ends - 1
dd offset GDT
IDTR_value dq 0000000007ffh
Label InterruptGATE_a dword
dw offset exception ; Offset[15..0]
dw Code32_Desc - GDT ; Selector
Label InterruptGATE_b dword
db 00000000b ; 0,0,0,WordCnt[4..0]
s_ACCESS <1,00b,0,0Eh> ; P,DPL,0,type = 386 interrupt Gate
dw 0 ; Offset[31..16]
;═════════════════ INITALIZATION ERROR MESSAGES ════════════════════════════
_inV86_err db ' Unable to enter protected mode because another protected mode ',10,13
db 'application is operating and does not support Dos Protected Mode Interface',10,13
db 'specifiaction.',10,13,10
db ' Disable the protected mode sofware and try again.',10,13,36
mesg_TimeOut8042 db 'Time out error in the keyboard controller (8042) failing to ',10,13,' respond on enabling the A20 gate.',10,13
all_DPMI_err db 'Encountered DPMI error: ',36
pmiERr db 'Switching to protecded mode.',10,13,36
No_Mem_err db 'Not Enough Base memory. 6000 bytes needed.',10,13,36
erralc_mesg db 'Can''t allocate descriptors.',10,13,36
errset_mesg db 'Can''t Set descriptors.',10,13,36
dpmi_aloc_err db 'Can''t allocate extended memory.',10,13,36
dpmi_lock_err db 'Unable to lock allocated memory.',10,13,36
dpmi_free_err db 'Unable to get free memory information.',10,13,36
mesgA20_err db 'ERROR: Physical A20 gate test failed.',10,13,36
xms_mesgA20_err db 'ERROR: XMS enabling the A20 gate.',10,13,36
xms_vers_err db 'Need XMS v3.0 or greater.',10,13,36
xms_alloc_Err db 'Can''t allocate XMS memory.',10,13,36
xms_lock_err db 'Can''t lock allocated XMS memory.',10,13,36
CALL_DATA Data_sruct <>
DosStart proc
mov ax,DATA32
mov fs,ax
mov fs:[psp_segment],DS ; store psp_segment
mov ax,DOS_CODE
mov ds,ax
; Get end of program address segment
mov bx,SP
shr bx,4
inc bx
mov ax,SS
add bx,ax
mov FS:Base_Segment,bx
; SET GLOBAL DISCRIPTOR TABLE Base Values ( USEING THE MACRO )
Fix_Desc_BASE Macro Descriptor,RealSeg
xor eax,eax
mov ax,RealSeg
shl eax,4
mov word ptr [Descriptor +2 ],ax
shr eax,16
mov byte ptr [Descriptor+ 4 ],al
ENDM
Fix_Desc_BASE PSP_desc ,fs:[psp_segment]
Fix_Desc_BASE CODE32_desc ,CODE32
Fix_Desc_BASE CODE16_desc ,CODE16
Fix_Desc_BASE DATA_desc ,DATA32
Fix_Desc_BASE DOS_CODE_desc ,DOS_CODE
Fix_Desc_BASE DOS_DATA_desc ,DOS_CODE
Fix_Desc_BASE TheStack_desc , TheSTACK
;------------------------- A 2 0 G A T E -------------------------------
; ENABLE THE A20 GATE
; If a XMS Driver is installed then use the Driver to enable the A20
; If it's done directly (with 8042) ,the XMS Driver will not have
; track of the A20 state and usualy ends up hanging the system.
;
;-----------------------------------------------------------------------------
; Look for XMS driver installation
mov ax,4300h
int 2fh
cmp al,80h
jnz No_XMS
; ELSE A XMS Driver is installed
push ES
mov ax,4310h ; get Driver entry point
int 2fh
mov word ptr xms_Driver,bx
mov word ptr xms_Driver+2,es
POP ES
; LOCAL ENABLE A20 GATE
mov ah,05h
call xms_Driver
cmp ax,1
Jz A20_XMS_OK
mov dx,offset xms_mesgA20_err
jmp exit_InitError
A20_XMS_OK:
jmp A20_Controlled ; ready to go protecded mode
;-- Waiting procedures for enabling the A20 directly --
Wait_until_status_bit0_is_1 proc
st0_clear:
xor cx,cx
in al,64h
test al,1
jnz st0_set
loop st0_clear
jmp A20_8042_timeout
st0_set: ret
endp
wait_until_status_bit1_is_0 proc
st1set: xor cx,cx
in al,64h
test al,2
jz st1_clear
loop st1set
jmp A20_8042_timeout
st1_clear: ret
endp
;----- jumps here if a time out error in enableing the A20 line ---
A20_8042_timeout:
mov dx,offset mesg_TimeOut8042
exit_InitError: mov ah,9 ; Prints error mesage and terminates
int 21h
call free_XMS_memory
mov ah,4ch
int 21h
No_XMS: ;------- Jumps here if no XMS driver is installed ---------------
;--- Must enable A20 directly through the 8042 ( keyboard controller)----
; It does this by setting bit 1 of the 8042's output port wich is
; inaccessable to the CPU Bus.
cli
call wait_until_status_bit1_is_0
mov al,0adh ;send disable keyboard command
out 64h,al ; viar 8042
call wait_until_status_bit1_is_0
mov al,0d0h ;Send read 8042 output port cmd
out 64h,al
call wait_until_status_bit0_is_1
in al,60h ; read the output port and save it
push ax
call wait_until_status_bit1_is_0
mov al,0d1h ; write output port cmd
out 64h,al
call wait_until_status_bit1_is_0
pop ax ; write data to the output port
or al,2
; and al,not 2
out 60h,al ; seting bit 1 > enables A20
call wait_until_status_bit1_is_0
mov al,0aeh ;enable keyboard again
out 64h,al
call wait_until_status_bit1_is_0 ; wait a bit more
;----- check if A20 really is enabled -------------
mov ax,0FFFFh
mov es,ax
mov ax,0
mov gs,ax
mov bl,gs:[0] ;Compare location 00000000 to 100000h
cmp es:[10h],bl ; Check if the same
jnz A20_enabled ; if not equal then A20 must be on.
not byte ptr es:[10h] ; Cange byte at adreess 100000h.
mov bl,es:[10h]
mov al,gs:[00]
not byte ptr es:[10h] ; Put back value
cmp al,bl ; Now see if the same
jnz A20_enabled
;--- EXIT on A20 error ----
mov dx , offset mesgA20_err
jmp exit_InitError ; print error mesg and exit
; --- A20 is deffently enabled ---
A20_enabled:
A20_Controlled: ; The A20 line should be enabled at this point
;-------------------------- A20 ACTIVE ------------------------------------
;-----------------------------------------------------------------------------
;════════════════════════════════════════════════════════════════════════
;══════════════════ SEE IF NEED TO USE DPMI OR NOT ═════════════════════
;════════════════════════════════════════════════════════════════════════
; USE DPMI TO ENTER PROTECTED MODE
; Obtain the Real (V86) to Protected Mode Switch Entry Point
mov ax,1687h
int 2Fh
and ax,ax
jnz No_DPMI
mov [DPMI_entry],di ; DPMI is installed
mov [DPMI_entry+2],es
mov fs:[Base_Segment],SS
mov ax,theStack ; use Protected Mode stack area
mov ss,ax
mov sp,Normal_stack
; Use memory for the DPMI OS private data area
mov es,fs:[Base_Segment]
add fs:Base_Segment,si
cmp fs:Base_Segment,09900h ; See if enough base memory
jae no_mem
call Allocate_Base ; Set descriptor base to here
mov eax,fs:[xms_usage]
mov xms_usage_tmp,eax
mov gs,fs:[psp_segment] ;Save environment pointer
push word ptr gs:[2Ch]
; Call the V86 To Protected Mode Switch Entry Point
mov ax,1 ; use 32 DPMI ( big stack )
call dword ptr [DPMI_entry]
Jc Cant_Enter_dmpiPMode
;************** NOW IN DPMI PROTECTED MODE ******************
; as a 16 bit but want 32 bit
push ds ; load ES to data segment
pop es
cmp xms_usage_tmp,0
jz No_DPMI_MEMORY
; Get Free memory info
mov ax,0500h
mov edi,offset Call_data
int 31h
mov word ptr Call_data.c_edx,offset dpmi_free_err
jc print_error
mov eax,dword ptr Call_data+08h ; get lockable size (pages)
shl eax,12 ; convert limit pages into Bytes
; Only Allocate memory defined in xms_usage
cmp eax,xms_usage_tmp
jbe LvDmpiSize
mov eax,xms_usage_tmp
LvDmpiSize: mov xms_usage_tmp,eax
mov ebx,eax
shr ebx,12
dec ebx
mov word ptr [XMS_desc+0],bx ; Set xms descriptor Limit
shr ebx,16
and bl,0fh
or byte ptr [XMS_desc+6],bl
; Allocate memory Block
mov cx,ax ; Olny allocate the Lockable memory
shr eax,16
mov bx,ax
mov ax,0501h
int 31h
mov word ptr Call_data.c_edx,offset dpmi_aloc_err
jc print_error
; Returns BX:CX with the linear address
mov word ptr [XMS_Desc+2],cx ; Set Desciptor base
mov byte ptr [XMS_Desc+4],bl
mov byte ptr [XMS_desc+7],bh
mov _tmpL_xms_base,CX ; store base address
mov _tmpH_xms_base,BX
No_DPMI_MEMORY:
; Set DPL for all descriptors to CPL
mov si,offset GDT + 13
setDPL:
or byte ptr [si],01100000b
add si,8
cmp si, 12*8 +5
jbe setDPL
; Allocate 12 descriptors
mov AX,0000h
mov CX,12
int 31h
mov word ptr Call_data.c_edx,offset erralc_mesg
jc print_error
mov DPMI_Selector,ax
;---- Set Descriptors -----
xor esi,esi
set_Descr:
mov ax,000Ch ; Set Descriptor
mov bx,DPMI_Selector
push bx
mov edi,offset GDT +8
mov edx,esi
shl edx,3
add edi,edx
int 31h
mov word ptr Call_data.c_edx,offset errset_mesg
jc print_error
mov ax,0003h ; Get Next Selector incremental value
int 31h
add DPMI_Selector,ax
inc esi
cmp esi,12 ; must set 12 descriptors
jb set_Descr
pop DS ; Pop all the selector values that were pushed.
ASSUME DS:DATA32
MOV DATA_sel,DS
POP CODE16_sel
POP CODE32_sel
POP PSP_sel
POP DOS_DATA_sel
POP DOS_CODE_sel
POP TheStack_sel
POP VIDEO_sel
POP BASE_sel
POP XMS_sel
POP FLAT_CODE32_sel
POP FLAT_DATA_sel
mov es,[PSP_Sel] ; Restore environment pointer
pop word ptr es:[02Ch]
mov es,DOS_data_sel
ASSUME ES:DOS_CODE
mov eax,ES:xms_usage_tmp
mov xms_usage,eax ; return store the acual amout allocted
mov eax,dword ptr ES:_tmpL_xms_base
mov xms_base,eax ; store the base address
; Get the base interrupt values of the PIC's
mov ax,0400h
int 31h
mov ES:PIC1_base,dh
mov ES:PIC2_base,dl
mov ax,0205h
mov cx,Code32_sel
; set int vector
setdmpiInts macro in
mov edx,offset irq&in
int 31h
inc bl
endm
mov bl,es:PIC1_base
x=0
rept 8
setdmpiInts %x
x=x+1
endm
mov bl,es:PIC2_base
x=8
rept 8
setdmpiInts %x
x=x+1
endm
mov edx,offset DPMI_EmulateRealInterupt
mov bl,20h
int 31h
mov ss,[TheStack_sel]
mov ss:[Real_ESP],0
mov ss:[Real_SS],0
mov esp,Normal_Stack
mov es:DPMI_entry,offset start32
mov ax,CODE32_sel
mov es:DPMI_entry+2,ax
;----- Jump to 32bit mode through CODE 32 descriptor -----
jmp dword ptr es:DPMI_entry
ASSUME DS:DOS_CODE
print_error:
push Call_data.c_edx
mov Call_data.c_edx,offset all_DPMI_err
call print
pop Call_data.c_edx
call print
dpmi_exit:
mov ah,4ch
int 21h
print proc near
mov Call_data.c_eax,0900h
mov Call_data.c_DS,DOS_CODE
mov ax,0300h ; sim real int
mov bl,21h
mov bh,0
mov edi,offset call_data
xor cx,cx
int 31h
ret
endp
No_DPMI:
;════════════════════════════════════════════════════════════════════════════
; Jups here if the operating system dos not support DPMI.
; Must enter protected mode directly.
;
;════════════════════════════════════════════════════════════════════════════
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
; See if in V86 mode Because if so we can't go any further
smsw ax ; Not allowed to use, MOV EAX,CR0
test al,1
jz in_Real_mode
mov dx,offset _inV86_err
jmp exit_InitError
in_Real_mode:
; See if enough base memory
cmp fs:Base_Segment,09A00h
ja no_mem
cmp xms_driver,00
jz No_XMS_MEMORY
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
; Use the XMS services to allocate extended memoey
cmp fs:xms_usage,0
jz Extended_mem_set
; Must have XMS V3.0 to work
mov ah,00 ; Get XMS Version number
call XMS_Driver
cmp ah,3
jae xms_V3
; mov dx,offset xms_vers_err
; jmp exit_InitError
xms_V3:
; QUERY FREE EXTENDED MEMORY
MOV AH,08h
call XMS_Driver ; returns eax with KB free
and eax,0ffffh
and al,0FCh ; want page granular
shl eax,10 ; put KB -> bytes
;Only Allocate memory defined in xms_usage
cmp eax,fs:xms_usage
jbe LvXmsSize
mov eax,fs:xms_usage
LvXmsSize: mov fs:xms_usage,eax
mov edx,eax
shr edx,10
and dl,0FCh ; want page granular
call set_xms_limit ; set limit to eax
; ALLOCATE ANY EXTENDED MEMORY BLOCK ( size in eDX )
mov ah,09h
call XMS_Driver
cmp ax,1
jz xms_allod
mov dx,offset xms_alloc_err
jmp exit_InitError
xms_allod:
mov XMS_handle,dx
; LOCK THE ALLOCATED EXTENDED MEMORY BLOCK
mov ah,0ch
mov dx,XMS_handle
call XMS_Driver
cmp ax,1
jz xms_locked
mov dx,offset xms_lock_err
jmp exit_InitError
xms_locked: ; DX:BX has "PHYSICAL" address.
mov word ptr [XMS_Desc+2],bx ;set xms descriptor
mov byte ptr [XMS_Desc+4],dl ; Base.
mov byte ptr [XMS_Desc+7],dh
mov word ptr fs:xms_base,BX ; set base of block
mov word ptr fs:xms_base+2,DX
jmp Extended_mem_set
No_XMS_MEMORY:
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
; ALLOCATE EVERY SINGLE BYTE OF EXTENDED MEMORY IF NO XMS DRIVER IS INSTALLED
; GET EXTENDED MEMORY SIZE FROM CMOS RAM -
mov al,24 ; get MSB
out 70h,al
in al,71h
shl ax,8
mov al,23 ; get LSB
out 70h,al
in al,71h
and eax,0ffffh
shl eax,10
mov fs:xms_usage,eax
call set_xms_limit ; set limit to eax
mov fs:xms_base,100000h ; start block at 1MB
Extended_mem_set:
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
; Extended memory is allocated at this point
CLI
in al,21h
mov oirqMask,al
in al,0a1h
mov oirqMask+1,al
;-- remap IRQ int vectors ---
mov bl,Pic_Base
mov bh,Pic_Base+8
call set_8259intvec
mov al,oirqMask
out 21h,al
mov al,oirqMask+1
out 0A1h,al
cli
; THE INTERRUPT DESCRIPTOR TABLE
; Use memory for the Interrupt Descriptor Table and the TSS
mov ax,fs:Base_Segment ; Set IDT Reg base
mov es,ax
and eax,0ffffh
shl eax,4
mov dword ptr IDTR_value+2,eax
mov fs:[IDT_base],eax
xor eax,eax ; Clear all the new memory
xor edi,edi
mov ecx,(8*256 +TSS_Ends+16)/4
cld
rep stosd
;--- Build the Interrupt Descriptor Table ---
mov eax,InterruptGATE_a
mov edx,InterruptGATE_B
xor cl,cl
xor si,si
@MakeIDT:
mov es:[si],eax ; Put into memory
mov es:[si+4],edx ; Put into memory
add si,8
dec cl
jnz @MakeIDT
;---- Set interrupt vector 31h ------
mov word ptr es:[31h*8],offset MyDPMI_services
;---- Set interrupt vector 21h ------
mov word ptr es:[21h*8],offset Go_REAL_MODE
mov word ptr es:[21h*8+2], Dos_Code_desc - GDT
; ---- Set hardware and exception interrupt handlers --------
setexecp macro n
mov word ptr es:[n*8],offset _386exception_&n
mov word ptr es:[(Pic_Base+n)*8],offset firstIRQ&n
endm
x=0
rept 16
setexecp %x
x=x+1
endm
; ---- Set general protection exception handler interrupt --------
mov word ptr es:[13*8],offset General_Exeption_Handler
; ---- Set real mode interrupt emulation handler interrupt --------
mov word ptr es:[20h*8],offset My_EmulateRealInterupt
;-- Build the Task State Segment --
add fs:Base_Segment,80h
mov es,fs:Base_Segment
xor eax,eax ; Get TSS base address
mov ax,es
shl eax,4
mov fs:tss_Level0ESP,eax ; Store address level0 ESP of TSS
add fs:tss_Level0ESP,offset tss_esp0
mov MyMain_TSS_Desc+2,ax ; Load Base address of TSS descriptor
shr eax,16
mov byte ptr MyMain_TSS_Desc+4,al
; Load important TSS fields
; The level0 ESP field is set when real mode interrupt emulation is called
mov es:tss_ss0, TheSTACK_Desc - GDT ; Priv. 0 SS
mov es:tss_iobase, 068h
mov es:tss_ioend,11111111b
; TSS is now built . Time to set the base descriptor base address just
; after the TSS and IDT.
add fs:Base_Segment,(TSS_Ends+15)/16 ; inc Base_Segment
call Allocate_Base
CLI ; Can't have interrupts anymore
; Load the Interrupt descriptor table register
lidt qword ptr IDTR_value
; Load the Global descriptor table register
mov EAX,DOS_CODE
shl EAX,4
add dword ptr GDTR_value+2 , EAX
lgdt qword ptr GDTR_value
; Enter Protected Mode
mov eax,CR0
or al,1 ; Set PE bit of CR0
mov CR0,eax
jmp FlushP ; Flush instruction prefetch counter
FlushP:
mov ax,MyMain_TSS_Desc - GDT ; Set TR to any valid TSS
ltr ax
mov ax,data_desc - GDT
mov ds,ax
assume ds:data32
mov ss,ds:[TheStack_sel] ; Setup Protected mode stack
mov esp,Normal_Stack
mov SS:[Real_SS],V86_Stack ; Setup initial V86 stack
mov SS:[Real_ESP ],V86_stack_size
db 0EAh ; Jump to 32bit mode through CODE 32 descr
dw offset Setup_Pmode , Code32_Desc - GDT
;--------------------------------------------------------------------------
; END OF PROTECTED MODE INITALIZATION
;--------------------------------------------------------------------------
;----------------------------------------------------------------------------
;───────────────────── INTERNAL ROUTINES ───────────────────────────────────
;----------------------------------------------------------------------------
assume ds:dos_code
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
set_xms_limit proc
; Set the xms descriptor limit.
shr eax,12
dec eax
mov word ptr [XMS_Desc+0],ax ; set limit [0..15]
shr eax,16
or byte ptr [XMS_desc+6],al ; limit [16..19]
ret
endp
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
Allocate_Base proc
mov ax,fs:Base_Segment ; Set BASE data descriptor to this
and eax,0ffffh
shl eax,4
mov word ptr [Base_Desc +2 ],ax
shr eax,16
mov byte ptr [Base_Desc +4 ],al
ret
ENDP
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
exit_error: mov ah,9 ; print error message
int 21h
jmp Exit_To_MSDOS
;∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·∙·
Cant_Enter_dmpiPMode: mov dx,offset pmiERr
jmp exit_error
No_Mem: mov dx,offset No_Mem_err
jmp exit_error
align 16
NON_DPMI_initalize_Size equ $ - NON_DPMI_initalize_start:
dosstart endp
DOS_CODE ENDS
TheSTACK SEGMENT public stack 'stack' USE32
db Normal_stack dup (?)
TheSTACK ENDS
V86_STACK SEGMENT public stack 'stack' USE16
db V86_stack_size dup (?)
V86_STACK ENDS
END DosStart