home *** CD-ROM | disk | FTP | other *** search
- ; PMODE v2.51 raw, DPMI, VCPI, & XMS compliant protected mode header.
- ; By Tran (a.k.a. Thomas Pytel).
-
- ; NASM (The Netwide Assembler) 0.95 port 0.1
- ; By Cyborg/Mistery <cyborg@otitsun.oulu.fi>
-
- ; NASM 0.97 port 0.2
- ; by Ike (a.k.a. Ivan Tomac) <ike@technologist.com>
-
- %include "nasmmac.inc"
-
- global v86r_eax ; D
- global v86r_ebx ; D
- global v86r_ecx ; D
- global v86r_edx ; D
- global v86r_esi ; D
- global v86r_edi ; D
- global v86r_ebp ; D
- global v86r_ah ; B
- global v86r_al ; B
- global v86r_bh ; B
- global v86r_bl ; B
- global v86r_ch ; B
- global v86r_cl ; B
- global v86r_dh ; B
- global v86r_dl ; B
- global v86r_ax ; W
- global v86r_bx ; W
- global v86r_cx ; W
- global v86r_dx ; W
- global v86r_si ; W
- global v86r_di ; W
- global v86r_bp ; W
- global v86r_ds ; W
- global v86r_es ; W
- global v86r_fs ; W
- global v86r_gs ; W
- global _selcode ; W
- global _seldata ; W
- global _selzero ; W
- global _lomembase ; D
- global _lomemtop ; D
- global _himembase ; D
- global _himemtop ; D
- global _pspa ; D
- global _code16a ; D
- global _code32a ; D
- global _getirqvect ; D
- global _setirqvect ; D
- global _sysbyte0 ; B
- global _setselector ; D
- global _exitcode ; B
-
- global _getmem ; near
- global _getlomem ; near
- global _gethimem ; near
- global _lomemsize ; near
- global _himemsize ; near
- global _ret ; near
- global _exit ; near
- global _getirqmask ; near
- global _setirqmask ; near
- global _rmpmirqset ; near
- global _rmpmirqfree ; near
- global _getselector ; near
- global _freeselector ; near
-
- extern _main
-
- LOWMIN equ 0 ; minimum free low memory (in K)
- EXTMIN equ 0 ; minimum free extended memory (in K)
- SELECTORS equ 8 ; extra selectors for allocation != 0
- STAKMAIN equ 100h ; main execution stream stack size (in para)
- STAKRMODE equ 10h ; real mode call stack size (in para)
- STAKPMODE equ 20h ; protected mode call stack size (in para)
- MODENESTING equ 8 ; max number of nested mode switches
-
- RMODENUM equ (MODENESTING+1) >> 1
- PMODENUM equ MODENESTING >> 1
- STAKSIZE equ STAKMAIN+(PMODENUM*STAKPMODE)+(RMODENUM*STAKRMODE) ;<0fffh!
-
- ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
- ; Real mode and 16bit code
- ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
-
- section code
- bits 16
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit common system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- errmsg0 db '386 or better not detected!!!',7,'$'
- errmsg1 db 'Not enough low memory!!!',7,'$'
- errmsg2 db 'System is already in V86 mode, and no VCPI or DPMI found!!!',7,'$'
- errmsg3 db 'Not enough extended memory!!!',7,'$'
- errmsg4 db 'Could not enable A20 gate!!!',7,'$'
- errmsg5 db 'Extended memory allocation failure. (weird eh???)',7,'$'
-
- nullint db 0CFh ; IRET instruction
- exitrout dw exit ; exit routine, modified if XMS, VCPI
-
- savedstakoff dw ? ; current saved stack offset
- savedstakseg dw ? ; current saved stack segment
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit common system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
-
- intreal: ; real mode int, load FS and GS here
- pushf
- ;-----------------------------------------------------------------------------
- callreal: ; real mode call, load FS and GS here
- push cs
- push W icreald
- mov fs,[cs:v86r_fs]
- mov gs,[cs:v86r_gs]
- mov eax,[cs:v86r_eax]
- mov ecx,[cs:v86r_ecx]
- mov edx,[cs:v86r_edx]
- mov ebx,[cs:v86r_ebx]
- mov esi,[cs:v86r_esi]
- mov edi,[cs:v86r_edi]
- mov ebp,[cs:v86r_ebp]
- ;-----------------------------------------------------------------------------
- icreal: ; real mode int, call, or IRQ
- db 66h,68h ; PUSH destination addx
- icrealm1 dd ? ;
- icrealm0 db ? ; CLI or STI
- retf
- ;-----------------------------------------------------------------------------
- icreald: ; done with real int or call
- cli
- pushf
- pop W[cs:v86r_flags]
- mov [cs:v86r_eax],eax
- mov [cs:v86r_ecx],ecx
- mov [cs:v86r_edx],edx
- mov [cs:v86r_ebx],ebx
- mov [cs:v86r_esi],esi
- mov [cs:v86r_edi],edi
- mov [cs:v86r_ebp],ebp
- mov [cs:v86r_ds],ds
- mov [cs:v86r_es],es
- mov [cs:v86r_fs],fs
- mov [cs:v86r_gs],gs
- icreald2:
- mov ax,cs
- mov ds,ax
- icrealm2: ; return to pmode modifiable to JMP
- ;-----------------------------------------------------------------------------
- mov ebx,[cp_savedstakoff] ; DPMI return to pmode
- mov dx,[dp_savedstaksel]
- mov edi,dp_int3_d
- mov si,[_selcode]
- mov cx,dx
- mov ax,[_seldata]
- jmp far [d_switchaddx]
- ;-----------------------------------------------------------------------------
- VICREAL1D equ (($-(icrealm2+2)) << 8) + 0EBh
- v_icreal1d: ; VCPI return to pmode from safe
- mov edi,cp_int3_d
- ;-----------------------------------------------------------------------------
- ; EDI=offset to jump to in code32
- v_switchtopmode: ; VCPI switch to pmode
- mov [v_ss_dest],edi
- mov esi,v_ss_cr3
- add esi,[_code16a]
- mov ax,0DE0Ch
- int 67h
- ;-----------------------------------------------------------------------------
- CICREAL1D equ (($-(icrealm2+2)) << 8) + 0EBh
- c_icreal1d: ; custom return to pmode from safe
- mov edi,cp_int3_d
- ;-----------------------------------------------------------------------------
- ; EDI=offset in pmode to jump to
- c_retpmode: ; reenter 32bit pmode
- lgdt [c_gdt32addx] ; set up pmode GDT and IDT
- lidt [c_idt32addx]
- mov B[gdt32task+5],89h ; set task as not busy
- mov eax,cr0 ; switch to pmode
- or al,1
- mov cr0,eax
- db 0EAh
- dw $+4,20h
- mov ax,30h ; load task register
- ltr ax
- jmp c_gotopmode
- ;═════════════════════════════════════════════════════════════════════════════
- int32: ; real mode INT32: EDX=off
- pushad
- push ds
- push es
- push fs
- push gs
- cli
- mov ax,cs
- mov ds,ax
- mov [p_cpmodem0],edx
- mov al,[esp+45]
- shr al,1
- and al,1
- add al,0FAh
- mov [p_cpmodem1],al
- push W[savedstakoff]
- push W[savedstakseg]
- movzx ebx,W[nextmodestack]
- lea eax,[ebx-STAKPMODE*16]
- mov [nextmodestack],ax
- add ebx,[realstackbase]
- mov [savedstakseg],ss
- int32m0: ; jump to pmode, modifiable
- ;-----------------------------------------------------------------------------
- sub sp,[dp_savelen]
- mov [savedstakoff],sp
- mov ax,ss ; DPMI jump to pmode
- mov es,ax
- mov di,sp
- xor al,al
- call far [d_saveaddx]
- mov ax,[_seldata]
- mov cx,ax
- mov dx,ax
- mov edi,p_cpmode0
- mov si,[_selcode]
- jmp far [d_switchaddx]
- ;-----------------------------------------------------------------------------
- VINT32 equ (($-(int32m0+2)) << 8) + 0EBh ; JMP short v_int32
- v_int32: ; VCPI call pmode
- push W[p_cpmodem2]
- mov W[p_cpmodem2],VCPMODED
- mov [savedstakoff],sp
- mov edi,p_cpmode1
- jmp v_switchtopmode
- ;-----------------------------------------------------------------------------
- ; if ($-(int32m0+2)) gt 127 => error
- CINT32 equ (($-(int32m0+2)) << 8)+0EBh ; JMP short c_int32
- c_int32: ; raw/XMS call pmode
- push W[p_cpmodem2]
- mov W[p_cpmodem2],CCPMODED
- mov [savedstakoff],sp
- mov edi,p_cpmode1
- jmp c_retpmode
- ;═════════════════════════════════════════════════════════════════════════════
- int32d0: ; DPMI done with pmode call
- mov di,sp
- mov al,1
- call far [d_saveaddx]
- add sp,[dp_savelen]
- ;-----------------------------------------------------------------------------
- int32d2: ; done from all
- pop W[savedstakseg]
- pop W[savedstakoff]
- add W[nextmodestack],STAKPMODE*16
- mov bx,[v86r_flags]
- mov ax,[esp+44]
- and ax,~8D5h
- and bx,8D5h
- or ax,bx
- mov [esp+44],ax
- pop gs
- pop fs
- pop es
- pop ds
- popad
- iret
- ;═════════════════════════════════════════════════════════════════════════════
- int32d1: ; VCPI done with pmode call
- mov ss,[savedstakseg]
- pop W[p_cpmodem2]
- jmp int32d2
- ;═════════════════════════════════════════════════════════════════════════════
- int32d3: ; raw/XMS done with pmode call
- mov W[c_retreal0m0],c_sicreal
- mov ax,cs
- mov ds,ax
- movzx esp,W[savedstakoff]
- mov ss,[savedstakseg]
- pop W[p_cpmodem2]
- jmp int32d2
- ;─────────────────────────────────────────────────────────────────────────────
- chek_VCPI: ; Chek for VCPI
- xor ax,ax
- mov gs,ax
- mov ax,[gs:67h*4]
- or ax,[gs:67h*4+2]
- jz short chekVCPIa
- mov ax,0DE00h
- int 67h
- or ah,ah
- clc
- jz short chekVCPId
- chekVCPIa:
- stc
- chekVCPId:
- ret
- ;─────────────────────────────────────────────────────────────────────────────
- chek_processor: ; Detect if current processor 386
- pushf
- xor ah,ah
- push ax
- popf
- pushf
- pop ax
- and ah,0F0h
- cmp ah,0F0h
- je short detectno386
- mov ah,0F0h
- push ax
- popf
- pushf
- pop ax
- and ah,0F0h
- jz short detectno386
- popf
- ret
- detectno386:
- mov dx,errmsg0
- jmp short exit16err
- ;─────────────────────────────────────────────────────────────────────────────
- chek_V86: ; Chek if already in V86 mode
- smsw ax
- test al,1
- mov dx,errmsg2
- jnz short exit16err
- ret
- ;─────────────────────────────────────────────────────────────────────────────
- pregetlomem: ; Get low memory or abort
- add eax,[_lomembase]
- mov ebx,[_lomemtop]
- cmp eax,ebx
- ja short pregetlomema
- mov ecx,eax
- xchg eax,[_lomembase]
- sub ebx,ecx
- cmp ebx,LOWMIN*1024
- jb short pregetlomema
- ret
- pregetlomema:
- mov dx,errmsg1
- ;─────────────────────────────────────────────────────────────────────────────
- exit16err: ; Exit program with message
- mov ah,9
- int 21h
- jmp [exitrout]
- ;-----------------------------------------------------------------------------
- exit: ; Guess what???
- movzx esp,sp
- mov ah,4Ch
- mov al,[_exitcode]
- int 21h
- ;═════════════════════════════════════════════════════════════════════════════
- ..start: ; Program begins here
- cli
- mov ax,stack
- mov ss,ax
- mov esp,STAKSIZE*16
-
- cld
- push cs
- pop ds
-
- call chek_processor ; is it at least a 386¿
-
- mov ax,es ; set up a bunch of pointers
- movzx eax,ax
- shl eax,4
- mov [_pspa],eax
- mov ax,cs
- movzx eax,ax
- shl eax,4
- mov [_code16a],eax
- or [gdt32code16+2],eax
- or [gdt32data16+2],eax
- mov bx,cs
- movzx ebx,bx
- shl ebx,4
- mov [_code32a],ebx
- or [gdt32code32+2],ebx
- or [gdt32data32+2],ebx
- add [c_gdt32addx+2],ebx
- mov ax,ss
- movzx eax,ax
- shl eax,4
- sub eax,ebx
- mov [_lomembase],eax
- mov [realstackbase],eax
- movzx eax,W[es:2]
- shl eax,4
- sub eax,ebx
- mov [_lomemtop],eax
-
- mov eax,STAKSIZE*16 ; get stack memory
- call pregetlomem
-
- push es ; save PSP seg (DPMI chek kills ES)
- pop fs
-
- call chek_VCPI ; chek for VCPI
- jnc near v_start
-
- mov ax,1687h ; chek for DPMI
- int 2Fh
- or ax,ax
- jz near d_start
-
- call chek_V86 ; chek for V86 mode
-
- mov ax,4300h ; chek for XMS
- int 2Fh
- cmp al,80h
- je near x_start
-
- jmp c_start ; custom system start
- ;─────────────────────────────────────────────────────────────────────────────
- enableA20: ; hardware enable gate A20
- xor ax,ax
- mov fs,ax
- dec ax
- mov gs,ax
- call testA20
- je short enableA20done
- in al,92h ; PS/2 A20 enable
- or al,2
- jmp short $+2
- jmp short $+2
- jmp short $+2
- out 92h,al
- call testA20
- je short enableA20done
- call enableA20o1 ; AT A20 enable
- jnz short enableA20wait
- mov al,0D1h
- out 64h,al
- call enableA20o1
- jnz short enableA20wait
- mov al,0dfh
- out 60h,al
- push W enableA20wait
- enableA20o1:
- mov ecx,20000h
- enableA20o1l:
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,64h
- test al,2
- loopnz enableA20o1l
- enableA20done:
- ret
- ;-----------------------------------------------------------------------------
- enableA20wait: ; wait for A20
- mov al,36h
- out 43h,al
- xor al,al
- out 40h,al
- out 40h,al
- mov cx,800h
- enableA20waitl0:
- call testA20
- je enableA20done
- in al,40h
- in al,40h
- mov ah,al
- enableA20waitl1:
- in al,40h
- in al,40h
- cmp al,ah
- je enableA20waitl1
- loop enableA20waitl0
- mov dx,errmsg4
- jmp exit16err
- ;-----------------------------------------------------------------------------
- testA20: ; Test for enabled A20
- mov al,[fs:0]
- mov ah,al
- not al
- mov [gs:10h],al
- cmp ah,[fs:0]
- mov [fs:0],ah
- ret
- ;─────────────────────────────────────────────────────────────────────────────
- ; BL=low PIC val, BH=high PIC val
- setintslots: ; set int nums in table to PIC vals
- mov edi,intslottbl
- mov cl,8
- setintslotsl0:
- mov [di],bl
- inc di
- inc bl
- dec cl
- jnz setintslotsl0
- mov cl,8
- setintslotsl1:
- mov [di],bh
- inc di
- inc bh
- dec cl
- jnz setintslotsl1
- ret
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit DPMI system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- d_errmsg0 db 'DPMI host is not 32bit!!!',7,'$'
- d_errmsg1 db 'Ran out of DPMI descriptors!!!',7,'$'
- d_errmsg2 db 'Could not set DPMI descriptors as needed!!!',7,'$'
- d_errmsg3 db 'Could not enter 32bit protected mode!!!',7,'$'
-
- d_enterpmode dw ?,? ; DPMI switch to pmode addx
- d_pspsel dw ? ; stupid PSP selector
- d_oldenvsegsel dw ? ; stupid selector we dont want
-
- d_switchaddx dd ? ; switch to pmode addx
- d_saveaddx dd ? ; save/restore state addx
-
- d_nintoff dd dp_irq0, dp_irq1, dp_irq2, dp_irq3
- dd dp_irq4, dp_irq5, dp_irq6, dp_irq7
- dd dp_irq8, dp_irq9, dp_irqa, dp_irqb
- dd dp_irqc, dp_irqd, dp_irqe, dp_irqf
- dd dp_int33, dp_int32
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit DPMI system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- d_retreal: ; Return to real mode
- mov ax,0205h ; restore all int vectors needed
- mov edi,17
- d_retreall0:
- mov bl,[intslottbl+edi]
- lea ebp,[edi*3]
- mov edx,D[ds:dp_ointbuf+ebp*2]
- mov cx,W[ds:dp_ointbuf+ebp*2+4]
- int 31h
- sub di,1
- jnc d_retreall0
- jmp short d_exit
- ;─────────────────────────────────────────────────────────────────────────────
- d_exit16err: ; DPMI Exit with error message
- mov W[v86r_ds],code
- mov B[v86r_ah],9
- mov ax,0300h
- mov bx,21h
- xor cx,cx
- mov edi,v86r_edi
- push ds
- pop es
- int 31h
- ;─────────────────────────────────────────────────────────────────────────────
- d_exit: ; DPMI exit to real mode
- mov es,[d_pspsel] ; restore env selector
- mov ax,[d_oldenvsegsel]
- mov [es:2Ch],ax
- jmp exit
- ;═════════════════════════════════════════════════════════════════════════════
- d_start: ; Start in a crappy DPMI system
- or B[_sysbyte0],3 ; set system type DPMI byte
-
- test bl,1 ; must be 32bit DPMI
- mov dx,d_errmsg0
- jz near exit16err
-
- mov [d_enterpmode+0],di ; store enter addx
- mov [d_enterpmode+2],es
- push W[fs:2Ch] ; preserve old env seg
-
- movzx eax,si ; get mem for DPMI blok
- shl eax,4
- call pregetlomem
- shr eax,4
- add ax,code
- mov es,ax
-
- mov ax,1 ; switch to pmode
- call far [d_enterpmode]
- cli ; I don't trust DPMI
- mov dx,d_errmsg3
- jc near exit16err
- mov W[v86r_dx],d_errmsg1 ; prepare for abort maybe
- pop ax ; swap old env seg with selector
- xchg ax,[es:2Ch]
- mov [d_oldenvsegsel],ax
- mov [d_pspsel],es ; store stupid selectors
- mov [data16sel],ds
- mov [code16sel],cs
- mov W[code16off],d_retreal ; set return to real mode addx
- mov D[_setirqvect],dp_setirqvect ; modify some crap
- mov D[_getirqvect],dp_getirqvect
- mov D[_setselector],dp_setselector
-
- push ds ; no more need for PSP
- pop es
- mov ax,0003h ; get selector increment value
- int 31h
- mov bx,ax
- xor ax,ax ; get needed selectors
- mov cx,3+SELECTORS
- int 31h
- jc near d_exit16err
-
- mov si,ax ; set up descriptors
- mov [_selcode],ax
- lea ecx,[eax+ebx]
- mov [_seldata],cx
- lea ebp,[ecx+ebx]
- mov [_selzero],bp
- lea eax,[ebp+ebx]
-
- mov [selectorbase],ax
- mov [selectorinc],bx
-
- mov W[v86r_dx],d_errmsg2
- mov ax,0Ch ; set descriptors from GDT
- mov bx,si
- mov edi,gdt32code32
- or B[edi+5],01100000b ; set DPL to 3
- int 31h
- jc near d_exit16err
- mov bx,cx
- mov edi,gdt32data32
- or B[edi+5],01100000b
- int 31h
- jc near d_exit16err
- mov bx,bp
- mov edi,gdt32zero32
- or B[edi+5],01100000b
- int 31h
- jc near d_exit16err
-
- mov bx,[selectorbase] ; set up extra allocatable selectors
- mov dx,SELECTORS
- d_startl1:
- int 31h ; initialize them all as gdt32zero32
- jc near d_exit16err
- add bx,[selectorinc]
- dec dx
- jnz d_startl1
-
- mov es,cx ; ES, FS, and GS what they should be
- mov fs,cx
- mov gs,bp
-
- mov edi,[_lomembase] ; chek and get extended memory
- mov eax,[_lomemtop]
- sub eax,edi
- cmp eax,48 ; 30h-byte buffer
- mov W[v86r_dx],errmsg1
- jb near d_exit16err
- mov ax,0500h
- int 31h
- mov edx,[es:edi]
- mov W[v86r_dx],errmsg3
- jmp short d_startf0
- d_startl2:
- sub edx,4096
- jnc short d_startf0
- xor edx,edx
- d_startf0:
- mov eax,edx
- shr eax,10
- cmp eax,EXTMIN
- jb near d_exit16err
- or edx,edx
- jz short d_startf1
- mov cx,dx
- shld ebx,edx,16
- mov ax,0501h
- int 31h
- jc d_startl2
- shl ebx,16
- mov bx,cx
- sub ebx,[_code32a]
- mov [_himembase],ebx
- add ebx,edx
- mov [_himemtop],ebx
- d_startf1:
-
- mov ax,0305h ; get save/restore state addxs
- int 31h
- mov [dp_savelen],ax
- mov [dp_saveaddx+0],edi
- mov [dp_saveaddx+4],si
- mov [d_saveaddx+0],cx
- mov [d_saveaddx+2],bx
- mov ax,0306h ; get switch mode addxs
- int 31h
- mov [dp_switchaddx+0],edi
- mov [dp_switchaddx+4],si
- mov [d_switchaddx+0],cx
- mov [d_switchaddx+2],bx
-
- mov ax,0400h ; set IRQ handlers to PIC values
- int 31h
- xchg dl,dh
- mov bx,dx
- call setintslots
-
- mov ah,2 ; backup and set all int vectors
- mov si,[_selcode]
- mov edi,17
- d_startl0:
- mov bl,[intslottbl+edi]
- mov al,4
- int 31h
- lea ebp,[edi*3]
- mov [ds:dp_ointbuf+ebp*2],edx
- mov [ds:dp_ointbuf+ebp*2+4],cx
- mov al,5
- mov edx,[d_nintoff+edi*4]
- mov cx,si
- int 31h
- sub di,1
- jnc d_startl0
-
- mov ax,es ; set up needed regs & go on to 32bit
- mov ss,ax
- add esp,[realstackbase]
- mov ds,ax
- push D[cs:_selcode]
- push D p_start
- db 66h,0CBh ; 32bit RETF
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16bit VCPI system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- v_errmsg0 db 'Incompatible VCPI PIC mappings!!!',7,'$'
-
- v_pagedirseg dw ? ; seg of page directory
- v_pagebase dw 0 ; first page of himem (*4)+1000h
- v_pagetop dw 0 ; top page of himem (*4)+1000h
-
- v_ss_cr3 dd ? ; new CR3 for pmode (physical)
- v_ss_gdtaddxptr dw c_gdt32addx,0 ; ptr to GDT data for pmode
- v_ss_idtaddxptr dw c_idt32addx,0 ; ptr to IDT data for pmode
- v_ss_ldtsel dw 0 ; don't need no stinkin LDTs
- v_ss_trsel dw 30h ; task state segment selector
- v_ss_dest dd ? ; start in pmode EIP
- dw 20h ; start in pmode CS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16bit VCPI system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- v_retreal: ; VCPI return to real mode
- movzx edi,W[exitrout]
- mov esi,esp
- sub esi,[realstackbase]
- mov cx,code
- ;═════════════════════════════════════════════════════════════════════════════
- ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
- v_retreal0: ; VCPI go to real mode
- sub esp,8
- push ecx
- push D[v86r_es]
- dw 06866h,stack,0 ; PUSH dword codeend
- push esi
- pushfd
- dw 06866h,code,0 ; PUSH dword code16
- push edi
- mov ax,gs
- mov ds,ax
- mov ax,0DE0Ch
- call D far [cs:vp_vcpipmentry]
- ;─────────────────────────────────────────────────────────────────────────────
- v_exit: ; VCPI exit (clean up pages)
- mov es,[v_pagedirseg]
- mov si,[v_pagebase]
- mov cx,[v_pagetop]
- sub cx,si
- jbe short v_exitf0
- v_exitl0:
- mov edx,[es:si]
- and dx,0F000h
- mov ax,0DE05h
- int 67h
- add si,4
- sub cx,4
- jnz v_exitl0
- v_exitf0:
- jmp exit
- ;─────────────────────────────────────────────────────────────────────────────
- v_exiterr1: ; VCPI not enough low mem exit
- mov dx,errmsg1
- jmp exit16err
- ;═════════════════════════════════════════════════════════════════════════════
- v_start: ; start continues from VCPI
- or B[_sysbyte0],2 ; set system type VCPI byte
- mov W[code16off],v_retreal ; VCPI return to real mode
- mov D[c_idt32handler+40h],vp_int33 ; VCPI safe int handlers
- mov D[c_idt32handler+44h],vp_int32
- mov D[cp_v86irqintr],vp_int33f0 ; VCPI IRQ safe int routine
- mov W[int32m0],VINT32 ; VCPI real INT32
-
- mov ax,0DE0Ah ; get PIC mappings
- int 67h
- mov bh,cl
- mov dx,v_errmsg0 ; chek for compatible PIC mapping
- cmp bl,bh
- je near exit16err
- cmp bl,30h
- je near exit16err
- cmp bh,30h
- je near exit16err
- mov ax,70h ; compatible, get highest needed num
- cmp al,bl
- ja short v_startf1
- mov al,bl
- v_startf1:
- cmp al,bh
- ja short v_startf2
- mov al,bh
- v_startf2:
- add al,7
- mov [c_numofintvects],al
- lea eax,[eax*8+7] ; set limit of IDT
- mov [c_idt32addx],ax
- call setintslots ; set int slots needed
- movzx eax,ax
- add eax,2068h+1
- call pregetlomem ; allocate TSS, IO bitmap, and IDT
- mov [cp_tssesp0ptr],eax
- mov eax,[_code16a] ; adjust mode switch structure
- add [v_ss_gdtaddxptr],eax
- add [v_ss_idtaddxptr],eax
-
- mov W[exitrout],v_exit ; set VCPI cleanup exit
-
- mov eax,[_lomembase] ; align lomem base on a page
- mov ebx,[_code32a]
- add ebx,eax
- lea ecx,[ebx+0FFFh]
- and ecx,0FFFFF000h
- sub ebx,ecx
- sub eax,ebx
- mov [_lomembase],eax
- mov ebp,[_lomemtop] ; get available low memory
- sub ebp,eax
- sub ebp,LOWMIN*1024 ; die if not enough
- jc near v_exiterr1
- cmp ebp,8192
- jb near v_exiterr1
-
- shld eax,ecx,28 ; get segment and clear all pages
- mov [v_pagedirseg],ax
- mov es,ax
- xor di,di
- mov cx,2048
- xor eax,eax
- rep stosd
- mov di,1000h ; get VCPI pmode interface
- mov esi,gdt32vcpi
- mov ax,0DE01h
- int 67h
- mov [vp_vcpipmentry],ebx
-
- mov [v_pagebase],di ; set up and go through allocation
- mov [v_pagetop],di
- movzx eax,di
- sub eax,1000h
- shl eax,10
- sub eax,[_code32a]
- mov [_himembase],eax
- mov ebx,8192
- v_startl2:
- mov ax,0DE04h
- int 67h
- or ah,ah
- jnz short v_startl2d
- test di,0FFFh
- jnz short v_startf4
- add ebx,4096
- cmp ebx,ebp
- jbe short v_startf4
- mov [v_pagetop],di
- mov ax,0DE05h
- int 67h
- jmp v_exiterr1
- v_startf4:
- and dx,0F000h
- or dl,7
- mov [es:di],edx
- add di,4
- jnc v_startl2
- v_startl2d:
- mov [v_pagetop],di
- lea si,[di-1000h]
- movzx eax,si
- shl eax,10
- sub eax,[_code32a]
- mov [_himemtop],eax
- sub di,[v_pagebase]
- cmp di,EXTMIN
- mov dx,errmsg3
- jb near exit16err
- add [_lomembase],ebx
-
- movzx ebx,W[v_pagedirseg] ; set up physical addresses
- shr ebx,8
- mov eax,[es:ebx*4+1000h]
- mov [v_ss_cr3],eax
- xor di,di
- v_startl3:
- inc ebx
- mov eax,[es:ebx*4+1000h]
- and ax,0F000h
- or al,7
- stosd
- sub si,1000h
- ja v_startl3
-
- mov edi,c_startf1 ; offset to jump to in pmode
- mov ebx,[cp_tssesp0ptr]
- jmp v_switchtopmode ; duh?
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit XMS system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- x_calladdx dd ? ; XMS driver addx
- x_handle dw 0FEDCh ; XMS handle of extended memory
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit XMS system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;─────────────────────────────────────────────────────────────────────────────
- x_exit: ; XMS exit (clean up allocation)
- mov ax,cs
- mov ds,ax
- mov dx,[x_handle]
- mov ah,0Dh
- call far [x_calladdx]
- mov ah,0Ah
- call far [x_calladdx]
- jmp exit
- ;─────────────────────────────────────────────────────────────────────────────
- x_exiterr5: ; exit with error message 5
- mov dx,errmsg5
- jmp exit16err
- ;═════════════════════════════════════════════════════════════════════════════
- x_start: ; start in an XMS system
- or B[_sysbyte0],1 ; set system type XMS byte
-
- mov ax,4310h ; get XMS driver addx
- int 2Fh
- mov [x_calladdx+0],bx
- mov [x_calladdx+2],es
-
- mov ah,3 ; XMS enable A20
- call far [x_calladdx]
- or ax,ax
- mov dx,errmsg4
- jz near exit16err
-
- mov ah,8 ; chek and get extended memory
- call far [x_calladdx]
- sub ax,64
- jnc short x_startf0
- xor ax,ax
- x_startf0:
- cmp ax,EXTMIN
- mov dx,errmsg3
- jb near exit16err
- mov dx,ax
- movzx ecx,ax
- shl ecx,10
- mov ah,9
- call far [x_calladdx]
- or ax,ax
- jz x_exiterr5
- mov [x_handle],dx
- mov W[exitrout],x_exit
- mov ah,0Ch
- call far [x_calladdx]
- or ax,ax
- jz x_exiterr5
- shrd eax,edx,16
- mov ax,bx
- sub eax,[_code32a]
- mov [_himembase],eax
- add eax,ecx
- mov [_himemtop],eax
-
- jmp c_startf0 ; go on to custom start
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit custom system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- c_idt16addx dw 3FFh, 0,0 ; default real mode IDT addx&limit
- c_idt32addx dw 3BFh, ?,? ; 32bit IDT addx&limit
- c_gdt32addx dw 04Fh+SELECTORS*8 ; 32bit GDT addx&limit
- dd gdt32 ;
-
- c_numofintvects db 77h ; number of int vects needed -1
- c_idt32handler dd cp_irq0, cp_irq1, cp_irq2, cp_irq3
- dd cp_irq4, cp_irq5
- dd cp_irq6, cp_irq7, cp_irq8, cp_irq9
- dd cp_irqa, cp_irqb
- dd cp_irqc, cp_irqd, cp_irqe, cp_irqf
- dd cp_int33, cp_int32, cp_int31
- dd cp_exc0, cp_exc1, cp_exc2, cp_exc3
- dd cp_exc4, cp_exc5
- dd cp_exc6, cp_exc7
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 16 bit custom system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- c_irqreal: ; real mode IRQ
- pushf
- push cs
- push W icreald2
- jmp icreal
- ;-----------------------------------------------------------------------------
- c_retreal1: ; load some real mode stuff & exit
- mov ax,stack
- mov ss,ax
- mov esp,STAKSIZE*10h
- jmp [exitrout]
- ;═════════════════════════════════════════════════════════════════════════════
- c_retreal0: ; load real mode IDT and set PE=0
- mov ax,28h
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov gs,ax
- mov ss,ax
- lidt [c_idt16addx]
- mov eax,cr0
- and al,0FEh
- mov cr0,eax
- db 0EAh ; JMP FAR PTR c_retreal0m0
- c_retreal0m0 dw c_sicreal,code
- ;-----------------------------------------------------------------------------
- c_sicreal: ; safe real mode int or call
- mov ax,stack
- mov ss,ax
- mov ds,[cs:v86r_ds]
- mov es,[cs:v86r_es]
- db 0EAh ; JMP FAR PTR c_sicrealm0
- c_sicrealm0 dw ?,code
- ;═════════════════════════════════════════════════════════════════════════════
- c_retreal: ; return to real mode
- mov W[c_retreal0m0],c_retreal1
- mov esp,STAKSIZE*10h
- jmp c_retreal0
- ;═════════════════════════════════════════════════════════════════════════════
- c_start: ; custom only start
- call enableA20 ; enable that stupid A20 thingy
-
- mov ah,88h ; chek and get extended mem
- int 15h
- cmp ax,EXTMIN
- mov dx,errmsg3
- jb near exit16err
- movzx eax,ax
- shl eax,10
- mov ebx,100000h
- sub ebx,[_code32a]
- mov [_himembase],ebx
- add eax,ebx
- mov [_himemtop],eax
- ;═════════════════════════════════════════════════════════════════════════════
- c_startf0: ; start continues from custom or XMS
- mov W[int32m0],CINT32 ; raw/XMS real INT32
- mov eax,2428h ; allocate TSS, IO bitmap, and IDT
- call pregetlomem
- mov ebx,eax
-
- lgdt [c_gdt32addx] ; switch to pmode
- mov eax,cr0
- or al,1
- mov cr0,eax
- db 0EAh
- dw $+4,20h
- ;-----------------------------------------------------------------------------
- ; EBX->TSS
- c_startf1: ; in 16bit pmode
- mov ax,28h ; set up segregs
- mov ds,ax
- mov al,18h
- mov gs,ax
- mov al,10h
- mov es,ax
- mov fs,ax
- mov ss,ax
- mov esp,STAKSIZE*16
- add esp,[realstackbase]
-
- mov W[v_ss_dest+4],8 ; VCPI enter 32bit pmode from now on
- lea eax,[ebx+4] ; addx of ESP0 in TSS
- mov [cp_tssesp0ptr],eax
- mov ebp,[_code32a] ; TSS location in mem to GDT
- lea eax,[ebx+ebp]
- mov ecx,gdt32task ; set up task
- or [ecx+2],eax
- mov B[ecx+5],89h
- mov cx,30h
- ltr cx
- add eax,2068h ; set up IDT
- mov ecx,c_idt32addx
- mov [ecx+2],eax
- lidt [ecx]
-
- mov D[es:ebx+8],10h ; set up TSS stuff (EBX->TSS)
- mov edi,104
- mov [es:ebx+102],di
- mov W[es:ebx+100],0
- add edi,ebx ; fill IO bitmap with 0
- xor eax,eax
- mov ecx,800h
- a32 rep stosd
-
- mov [cp_idt32ptr],edi ; set up blank IDT entries
- movzx esi,B[c_numofintvects]
- c_startl0: ; set up interrupt gates
- mov D[es:edi+esi*8],80000h+cp_excf ; offset, selector 8h
- mov D[es:edi+esi*8+4],(10001110b<<8) ; P=1, DPL=0
- sub si,1
- jnc c_startl0
- mov si,1Ah ; necessary IDT entries
- c_startl1:
- movzx ebp,B[intslottbl+esi]
- mov eax,[c_idt32handler+esi*4]
- c_startl1c:
- mov [es:edi+ebp*8],ax
- sub si,1
- jnc c_startl1
-
- mov edi,p_start ; set up regs & go on to 32bit
- mov ax,10h
- mov ds,ax
- ;-----------------------------------------------------------------------------
- c_gotopmode: ; jump to 32bit pmode
- pushfd ; set eflags: NT=0, IOPL=3
- pop eax
- and ah,10111111b ; NT=0
- or ah,00110000b ; IOPL=3
- push eax
- popfd
- dw 6866h,8,0 ; PUSH dword 8
- push edi
- db 66h,0CBh ; 32bit RETF
-
- ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
- ; 32bit pmode code
- ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
-
- bits 32
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit common system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- _lomembase dd ? ; low mem base for allocation
- _lomemtop dd ? ; top of low mem
- _himembase dd 0 ; high mem base for allocation
- _himemtop dd 0 ; top of high mem
- _pspa dd ? ; offset of start of PSP from 0
- _code16a dd ? ; offset of start of 16bit code from 0
- _code32a dd ? ; offset of start of 32bit code from 0
- _selcode dw 8 ; code segment selector
- _seldata dw 10h ; data segment alias for code
- _selzero dw 18h ; data segment starting at 0:0
- _sysbyte0 db 0 ; system bits:
- ; 0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
- _exitcode db 0 ; exit code for int21h ah=4ch
-
- ALIGNZ(4)
- _getirqvect dd cp_getirqvect ; get IRQ handler offset routine addx
- _setirqvect dd cp_setirqvect ; set IRQ handler offset routine addx
- _setselector dd cp_setselector ; set a selector addx offset addx
-
- ; /limit15-0\ /base23-0\ /G,X,O,AVL,limit19-16\ /base31-24\
- gdt32 dd 0,0 ; /P,DPL,1,TYPE,A\ ; 0h
- gdt32code32 db 0FFh, 0FFh, 0, 0, 0, 10011010b, 11001111b, 0 ; 8h
- gdt32data32 db 0FFh, 0FFh, 0, 0, 0, 10010010b, 11001111b, 0 ; 10h
- gdt32zero32 db 0FFh, 0FFh, 0, 0, 0, 10010010b, 11001111b, 0 ; 18h
- gdt32code16 db 0FFh, 0FFh, 0, 0, 0, 10011010b, 0, 0 ; 20h
- gdt32data16 db 0FFh, 0FFh, 0, 0, 0, 10010010b, 0, 0 ; 28h
- gdt32task db 0FFh, 0FFh, 0, 0, 0, 10001001b, 0, 0 ; 30h
- gdt32vcpi dd ?,? ; 38h
- dd ?,? ; 40h
- dd ?,? ; 48h
- gdt32free times SELECTORS db 0FFh,0FFh, 0,0,0, 10010010b,11001111b, 0
-
- v86r_edi: ; vregs for pmode<>real communication
- v86r_di dw ?, ? ; needs to stay this way cuz its a
- v86r_esi: ; stupid DPMI structure thingy
- v86r_si dw ?, ?
- v86r_ebp:
- v86r_bp dw ?, ?
- dd 0
- v86r_ebx:
- v86r_bx:
- v86r_bl db ?
- v86r_bh db ?, ?,?
- v86r_edx:
- v86r_dx:
- v86r_dl db ?
- v86r_dh db ?, ?,?
- v86r_ecx:
- v86r_cx:
- v86r_cl db ?
- v86r_ch db ?, ?,?
- v86r_eax:
- v86r_ax:
- v86r_al db ?
- v86r_ah db ?, ?,?
- v86r_flags dw ?
- v86r_es dw ?
- v86r_ds dw ?
- v86r_fs dw ?
- v86r_gs dw ?
- dd 0,0
-
- oint1bvect dd ? ; old real int 1Bh vector (ctrl+break)
- oint32vect dd ? ; old real int 32h vector
- oirqmask dw ? ; old port 21h and 0A1h masks
- intslottbl db 8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,70h,71h,72h,73h,74h,75h,76h,77h
- db 33h,32h,31h,0,1,2,3,4,5,6,7
-
- selectorbase dw 50h
- selectorinc dw 8
- selectorfree times SELECTORS db 0
-
- code16off dw c_retreal ; offset in 16bit of exit function
- code16sel dw 20h ; 16bit pmode code selector
- data16sel dw 28h ; 16bit pmode data selector
-
- nextmodestack dw (STAKSIZE-STAKMAIN)*16 ; stack for next mode switch
- realstackbase dd ? ; linear ptr to beginning of codeend
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit common system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- p_cpmode2: ; call pmode from V86
- mov gs,cx
- mov cl,10h
- mov ds,cx
- mov es,cx
- mov fs,cx
- sub W[nextmodestack],STAKPMODE*16
- push W[p_cpmodem2]
- mov W[p_cpmodem2],V86CPMODED
- mov eax,[esp+22]
- mov [p_cpmodem0],eax
- mov al,[esp+43]
- shr al,1
- and al,1
- add al,0FAh
- mov [p_cpmodem1],al
- jmp short p_cpmode
- ;═════════════════════════════════════════════════════════════════════════════
- p_cpmode1: ; call pmode, load all
- mov esp,ebx
- mov ax,10h
- mov ds,ax
- mov es,ax
- mov ss,ax
- ;-----------------------------------------------------------------------------
- p_cpmode0: ; call pmode, load FS and GS
- mov fs,[_seldata]
- mov gs,[_selzero]
- ;-----------------------------------------------------------------------------
- p_cpmode: ; call pmode routine from real
- push D p_cpmoded
- cld
- mov eax,[v86r_eax]
- mov ecx,[v86r_ecx]
- mov edx,[v86r_edx]
- mov ebx,[v86r_ebx]
- mov esi,[v86r_esi]
- mov edi,[v86r_edi]
- mov ebp,[v86r_ebp]
- db 68h ; PUSH destination address
- p_cpmodem0 dd ? ;
- p_cpmodem1 db ? ; CLI or STI
- ret
- ;-----------------------------------------------------------------------------
- p_cpmoded: ; call to pmode done
- cli
- pushf
- pop W[v86r_flags]
- mov [v86r_eax],eax
- mov [v86r_ecx],ecx
- mov [v86r_edx],edx
- mov [v86r_ebx],ebx
- mov [v86r_esi],esi
- mov [v86r_edi],edi
- mov [v86r_ebp],ebp
- mov ecx,[_code16a]
- p_cpmodem2: ; return to real, modifiable to JMP
- ;-----------------------------------------------------------------------------
- movzx ebx,W[gs:savedstakoff+ecx] ; DPMI return to real mode
- mov dx,[gs:savedstakseg+ecx]
- mov ax,code
- mov cx,dx
- mov si,ax
- mov edi,int32d0
- jmp D far [dp_switchaddx]
- ;-----------------------------------------------------------------------------
- VCPMODED equ (($-(p_cpmodem2+2)) << 8) + 0EBh
- p_cpmoded2: ; VCPI done with pmode
- movzx esi,W[gs:savedstakoff+ecx]
- mov cx,code
- mov edi,int32d1
- db 0EAh ; 16bit JMP FAR 20h:v_retreal0
- dw v_retreal0,0,20h ;
- ;-----------------------------------------------------------------------------
- CCPMODED equ (($-(p_cpmodem2+2)) << 8) + 0EBh
- p_cpmoded3: ; raw/XMS done with pmode
- mov W[gs:c_retreal0m0+ecx],int32d3
- db 0EAh ; 16bit JMP FAR 20h:c_retreal0
- dw c_retreal0,0,20h ;
- ;-----------------------------------------------------------------------------
- ; if ($-(p_cpmodem2+2)) gt 127 => error
- V86CPMODED equ (($-(p_cpmodem2+2)) << 8) + 0EBh
- p_cpmoded4: ; V86 done with pmode
- pop W[p_cpmodem2]
- jmp cp_int3_d3
- ;═════════════════════════════════════════════════════════════════════════════
- p_start: ; common 32bit start
- mov eax,[gs:1Bh*4] ; neutralize crtl+break
- mov [oint1bvect],eax
- db 65h,67h,0C7h,6 ; MOV DWORD PTR GS:[1bh*4],code16:nullint
- dw 1Bh*4,nullint,code ;
- mov eax,[gs:32h*4] ; set up for new real mode INT32
- mov [oint32vect],eax
- db 65h,67h,0C7h,6 ; MOV DWORD PTR GS:[32h*4],code16:int32
- dw 32h*4,int32,code ;
- in al,21h ; save old PIC masks
- mov ah,al
- in al,0A1h
- mov [oirqmask],ax
- jmp _main ; go to main code
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Allocate any mem, (first cheks low, then high)
- ; In:
- ; EAX - size requested
- ; Out:
- ; CF=0 - memory allocated
- ; CF=1 - not enough mem
- ; EAX - linear pointer to mem or ?
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _getmem:
- push eax
- call _getlomem
- jnc short getmemd
- pop eax
- jmp short _gethimem
- getmemd:
- add esp,4
- _ret: ; generic RET instruction
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Allocate some low mem
- ; In:
- ; EAX - size requested
- ; Out:
- ; CF=0 - memory allocated
- ; CF=1 - not enough mem
- ; EAX - linear pointer to mem or ?
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _getlomem:
- add eax,[_lomembase]
- cmp eax,[_lomemtop]
- ja short getmemerr
- xchg eax,[_lomembase]
- clc
- ret
- getmemerr:
- stc
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Allocate some high mem
- ; In:
- ; EAX - size requested
- ; Out:
- ; CF=0 - memory allocated
- ; CF=1 - not enough mem
- ; EAX - linear pointer to mem or ?
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _gethimem:
- add eax,[_himembase]
- cmp eax,[_himemtop]
- ja short getmemerr
- xchg eax,[_himembase]
- clc
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Get amount of free low mem
- ; Out:
- ; EAX - number of bytes free
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _lomemsize:
- mov eax,[_lomemtop]
- sub eax,[_lomembase]
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Get amount of free high mem
- ; Out:
- ; EAX - number of bytes free
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _himemsize:
- mov eax,[_himemtop]
- sub eax,[_himembase]
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Get status of IRQ mask bit
- ; In:
- ; BL - IRQ num (0-15)
- ; Out:
- ; AL - status: 0=enabled, 1=disabled
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _getirqmask:
- push ax
- in al,0A1h
- mov ah,al
- in al,21h
- xchg cl,bl
- shr ax,cl
- xchg cl,bl
- and al,1
- mov [esp],al
- pop ax
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Set status of IRQ mask bit
- ; In:
- ; BL - IRQ num (0-15)
- ; AL - status: 0=enabled, 1=disabled
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _setirqmask:
- push ax
- push bx
- push cx
- push dx
- mov cl,bl
- mov bx,0FFFEh
- movzx dx,al
- rol bx,cl
- shl dx,cl
- in al,0A1h
- mov ah,al
- in al,21h
- and ax,bx
- or ax,dx
- out 21h,al
- mov al,ah
- out 0A1h,al
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Set a real mode IRQ vect to redirect to pmode
- ; In:
- ; BL - IRQ number
- ; EDX - offset of IRQ handler
- ; EDI -> 21 byte buffer for code stub created
- ; Out:
- ; EAX - old seg:off of real mode IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- rmpmirqsetd0:
- db 66h,52h ; PUSH EDX
- db 66h,0BAh,?,?,?,? ; MOV EDX,?
- db 0CDh,32h ; INT 32h
- db 66h,5Ah ; POP EDX
- db 0CFh ; IRET
- db 9Ch ; PUSHFD
- db 0Eh ; PUSH CS
- db 0E8h,?,?,?,? ; CALL ?
- db 0C3h ; RET
- ;-----------------------------------------------------------------------------
- _rmpmirqset:
- push esi
- push edi
- mov esi,rmpmirqsetd0
- lea eax,[edi+13]
- mov [esi+4],eax
- add eax,7
- sub eax,edx
- neg eax
- mov [esi+16],eax
- mov eax,edi
- movsd
- movsd
- movsd
- movsd
- movsd
- movsb
- add eax,[_code32a]
- shl eax,12
- shr ax,12
- movzx edi,bl
- cmp edi,8
- jb short rmpmirqsetf0
- add edi,60h
- rmpmirqsetf0:
- xchg eax,[gs:edi*4+20h]
- pop edi
- pop esi
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Reset a real more IRQ vect back to normal (just sets real mode IRQ vect)
- ; In:
- ; BL - IRQ number
- ; EAX - seg:off of real mode IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _rmpmirqfree:
- push ebx
- movzx ebx,bl
- cmp bl,8
- jb short rmpmirqfreef0
- add bl,60h
- rmpmirqfreef0:
- mov [gs:ebx*4+20h],eax
- pop ebx
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Allocate a selector
- ; Out:
- ; CF=1 - selector not allocated
- ; CF=0 - selector allocated
- ; AX - 4G data selector or ?
- ; Notes:
- ; The selector returned is for a 4G r/w data segment with an undefined base
- ; address.
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _getselector:
- push ecx
- push edi
- mov edi,selectorfree
- mov ecx,SELECTORS
- mov al,0
- repne scasb
- jne short getselectorf0
- mov B[edi-1],1
- sub ecx,SELECTORS-1
- neg ecx
- imul cx,[selectorinc]
- mov ax,[selectorbase]
- add ax,cx
- clc
- jmp short getselectorf1
- getselectorf0:
- stc
- getselectorf1:
- pop edi
- pop ecx
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Free an allocated selector
- ; In:
- ; AX - selector
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _freeselector:
- push eax
- push dx
- sub ax,[selectorbase]
- xor dx,dx
- div W[selectorinc]
- movzx eax,ax
- mov B[selectorfree+eax],0
- pop dx
- pop eax
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Exit to real mode
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _exit:
- cli
- mov eax,[oint1bvect] ; restore ctrl+break
- mov [gs:1Bh*4],eax
- mov eax,[oint32vect] ; restore real mode int 32h vector
- mov [gs:32h*4],eax
- mov ax,[oirqmask] ; restore PIC masks
- out 0A1h,al
- mov al,ah
- out 21h,al
- push W[code16sel] ; go to 16bit pmode exit code
- push W[code16off]
- mov ds,[data16sel]
- db 66h,0CBh ; 16bit RETF
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit DPMI system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- dp_switchaddx dw ?,?,? ; switch to real mode addx
- dp_saveaddx dw ?,?,? ; save/restore state addx
- dp_savelen dw 0,0 ; length of state buffer
- dp_savedstaksel dw ? ; current saved stack selector
-
- dp_ointbuf times 18 dw ?,?,? ; saved interrupt addx buffer
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit DPMI system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- dp_int32: ; DPMI INT32/34: CX:DX=seg:off
- pushad
- shl ecx,16
- mov cx,dx
- mov bp,callreal
- mov dl,1
- jmp short dp_int3_
- ;═════════════════════════════════════════════════════════════════════════════
- dp_int33: ; DPMI INT33/35: AL=int num
- pushad
- movzx eax,al
- mov ecx,[gs:eax*4]
- mov bp,intreal
- xor dl,dl
- ;-----------------------------------------------------------------------------
- dp_int3_: ; DPMI int or call to real mode
- mov ax,0900h
- int 31h
- push ax
- and al,dl
- add al,0FAh
- mov ebx,[_code16a]
- mov [gs:icrealm0+ebx],al
- mov [gs:icrealm1+ebx],ecx
- push D[cp_savedstakoff]
- push W[dp_savedstaksel]
- movzx ebx,W[nextmodestack]
- lea eax,[ebx-STAKRMODE*16]
- mov [nextmodestack],ax
- mov ax,ss
- mov es,ax
- sub esp,[dp_savelen]
- mov edi,esp
- xor al,al
- call D far [dp_saveaddx]
- mov [cp_savedstakoff],esp
- mov [dp_savedstaksel],ss
- mov dx,stack
- mov ax,[v86r_ds]
- mov cx,[v86r_es]
- movzx edi,bp
- mov si,code
- jmp D far [dp_switchaddx]
- ;-----------------------------------------------------------------------------
- dp_int3_d: ; done with real mode int or call
- mov edi,esp
- mov al,1
- call D far [dp_saveaddx]
- add esp,[dp_savelen]
- pop W[dp_savedstaksel]
- pop D[cp_savedstakoff]
- add W[nextmodestack],STAKRMODE*16
- mov bx,[v86r_flags]
- pop ax
- int 31h
- mov ax,ds
- mov es,ax
- mov fs,ax
- mov gs,[_selzero]
- jmp cp_int3_d2
- ;═════════════════════════════════════════════════════════════════════════════
- ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
- dp_irq0: jmp D far [cs:dp_ointbuf+0]
- dp_irq1: jmp D far [cs:dp_ointbuf+6]
- dp_irq2: jmp D far [cs:dp_ointbuf+12]
- dp_irq3: jmp D far [cs:dp_ointbuf+18]
- dp_irq4: jmp D far [cs:dp_ointbuf+24]
- dp_irq5: jmp D far [cs:dp_ointbuf+30]
- dp_irq6: jmp D far [cs:dp_ointbuf+36]
- dp_irq7: jmp D far [cs:dp_ointbuf+42]
- dp_irq8: jmp D far [cs:dp_ointbuf+48]
- dp_irq9: jmp D far [cs:dp_ointbuf+54]
- dp_irqa: jmp D far [cs:dp_ointbuf+60]
- dp_irqb: jmp D far [cs:dp_ointbuf+66]
- dp_irqc: jmp D far [cs:dp_ointbuf+72]
- dp_irqd: jmp D far [cs:dp_ointbuf+78]
- dp_irqe: jmp D far [cs:dp_ointbuf+84]
- dp_irqf: jmp D far [cs:dp_ointbuf+90]
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; DPMI get IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; Out:
- ; EDX - offset of IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- dp_getirqvect:
- push ax
- push ebx
- push cx
- movzx ebx,bl
- mov bl,[intslottbl+ebx]
- mov ax,0204h
- int 31h
- pop cx
- pop ebx
- pop ax
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; DPMI set IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; EDX - offset of IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- dp_setirqvect:
- push ax
- push ebx
- push cx
- movzx ebx,bl
- mov bl,[intslottbl+ebx]
- mov cx,cs
- mov ax,0205h
- int 31h
- pop cx
- pop ebx
- pop ax
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Set the base addx for a selector
- ; In:
- ; AX - selector
- ; EDX - linear base addx for selector
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- dp_setselector:
- push ax
- push bx
- push ecx
- shld ecx,edx,16
- mov bx,ax
- mov ax,7
- int 31h
- pop ecx
- pop bx
- pop ax
- ret
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit custom/XMS/VCPI system data
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- vp_vcpipmentry dw 0,0,38h ; VCPI entry point in pmode
-
- cp_tssesp0ptr dd 0 ; ptr to ESP0 in TSS, or null in VCPI
- cp_idt32ptr dd ? ; ptr to 32bit IDT
- cp_validexcdesp dd 0 ; valid ESP value for exc 13
-
- cp_v86irqintr dd cp_int33f0
- cp_v86irqnum db ? ; IRQ num for V86 mode
- cp_savedstakoff dd ? ; current saved stack offset
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; 32 bit custom/XMS/VCPI system code
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ;═════════════════════════════════════════════════════════════════════════════
- cp_int31: ; INT 31h: AX=900h,901h,902h
- cmp al,1
- mov al,[esp+9]
- jb short cp_int31f0
- ja short cp_int31f1
- or B[esp+9],2
- jmp short cp_int31f1
- cp_int31f0:
- and B[esp+9],0FDh
- cp_int31f1:
- shr al,1
- and al,1
- iretd
- ;═════════════════════════════════════════════════════════════════════════════
- vp_int32: ; VCPI INT 32h: safe CX:DX=seg:off
- pushad
- mov ebp,callreal
- mov si,VICREAL1D
- mov bl,2
- jmp short cp_int34f0
- ;═════════════════════════════════════════════════════════════════════════════
- vp_int33: ; VCPI INT 33h: safe AL=int num
- pushad
- mov ebp,intreal
- ;-----------------------------------------------------------------------------
- vp_int33f0:
- mov si,VICREAL1D
- mov bl,2
- jmp short cp_int35f0
- ;═════════════════════════════════════════════════════════════════════════════
- cp_int32: ; INT 32h: safe CX:DX=seg:off
- pushad
- mov ebp,callreal
- mov si,CICREAL1D
- mov bl,1
- jmp short cp_int34f0
- ;═════════════════════════════════════════════════════════════════════════════
- cp_int33: ; INT 33h: safe AL=int num
- pushad
- mov ebp,intreal
- ;-----------------------------------------------------------------------------
- cp_int33f0:
- mov si,CICREAL1D
- mov bl,1
- jmp short cp_int35f0
- ;-----------------------------------------------------------------------------
- cp_int34f0: ; relic from times past
- shl ecx,16
- mov cx,dx
- mov bh,1
- jmp short cp_int3_
- ;-----------------------------------------------------------------------------
- cp_int35f0: ; another one, but functional
- movzx eax,al
- mov ecx,[gs:eax*4]
- xor bh,bh
- ;-----------------------------------------------------------------------------
- cp_int3_: ; int or call to real mode
- mov edi,[esp+40]
- shld eax,edi,23
- and al,bh
- add al,0FAh
- mov edx,[_code16a]
- mov [gs:icrealm0+edx],al
- mov [gs:icrealm1+edx],ecx
- xchg [gs:icrealm2+edx],si
- push si
- movzx esi,W[nextmodestack]
- lea eax,[esi-STAKRMODE*16]
- mov [nextmodestack],ax
- add eax,[realstackbase]
- mov edx,[cp_tssesp0ptr]
- push D[edx]
- mov [edx],eax
- sub eax,40
- push D[cp_validexcdesp]
- mov [cp_validexcdesp],eax
- push D[cp_savedstakoff]
- mov [cp_savedstakoff],esp
- cmp bl,1
- ja short vp_int3_s
- ;-----------------------------------------------------------------------------
- cp_int3_s: ; safe real mode int or call
- mov edx,[_code16a]
- mov [gs:c_sicrealm0+edx],bp
- mov esp,esi
- db 0EAh ; 16bit JMP FAR 20h:c_retreal0
- dw c_retreal0,0,20h ;
- ;-----------------------------------------------------------------------------
- vp_int3_s: ; safe VCPI real mode int or call
- mov edi,ebp
- mov cx,[v86r_ds]
- mov ax,28h
- mov ds,ax
- db 0EAh ; 16bit JMP FAR 20h:v_retreal0
- dw v_retreal0,0,20h ;
- ;-----------------------------------------------------------------------------
- cp_int3_d: ; done with real mode int or call
- mov ax,18h
- mov gs,ax
- mov ax,10h
- mov ds,ax
- mov es,ax
- mov fs,ax
- mov ss,ax
- mov esp,[cp_savedstakoff]
- pop D[cp_savedstakoff]
- pop D[cp_validexcdesp]
- mov ebx,[cp_tssesp0ptr]
- pop D[ebx]
- mov ebx,[_code16a]
- pop W[gs:icrealm2+ebx]
- ;-----------------------------------------------------------------------------
- cp_int3_d3: ; done from real mode pmode call
- add W[nextmodestack],STAKRMODE*16
- mov bx,[v86r_flags]
- ;-----------------------------------------------------------------------------
- cp_int3_d2: ; done from DPMI also
- mov ax,[esp+40]
- and ax,~8D5h
- and bx,8D5h
- or ax,bx
- mov [esp+40],ax
- popad
- iretd
- ;═════════════════════════════════════════════════════════════════════════════
- ; low 8 exceptions and undefined interrupt.
- cp_exc0:
- push eax
- xor al,al
- jmp cp_irq
- cp_exc1:
- push eax
- mov al,1
- jmp cp_irq
- cp_exc2:
- push eax
- mov al,2
- jmp cp_irq
- cp_exc3:
- push eax
- mov al,3
- jmp cp_irq
- cp_exc4:
- push eax
- mov al,4
- jmp cp_irq
- cp_exc5:
- push eax
- mov al,5
- jmp cp_irq
- cp_exc6:
- pushad
- mov al,6
- jmp short cp_exc
- cp_exc7:
- push eax
- mov al,7
- jmp cp_irq
- cp_excf:
- pushad
- mov al,0FFh
- ;-----------------------------------------------------------------------------
- cp_exc: ; main exception handler
- mov bx,10h
- mov ds,bx
- mov es,bx
- mov fs,bx
- mov gs,[_selzero]
- cld
- jmp _exit
- ;═════════════════════════════════════════════════════════════════════════════
- ; IRQ redirector between modes
- cp_irq0:
- push eax
- mov al,08h
- jmp short cp_irq
- cp_irq1:
- push eax
- mov al,09h
- jmp short cp_irq
- cp_irq2:
- push eax
- mov al,0Ah
- jmp short cp_irq
- cp_irq3:
- push eax
- mov al,0Bh
- jmp short cp_irq
- cp_irq4:
- push eax
- mov al,0Ch
- jmp short cp_irq
- cp_irq5:
- push eax
- mov al,0Dh
- jmp short cp_irq
- cp_irq6:
- push eax
- mov al,0Eh
- jmp short cp_irq
- cp_irq7:
- push eax
- mov al,0Fh
- jmp short cp_irq
- cp_irq8:
- push eax
- mov al,70h
- jmp short cp_irq
- cp_irq9:
- push eax
- mov al,71h
- jmp short cp_irq
- cp_irqa:
- push eax
- mov al,72h
- jmp short cp_irq
- cp_irqb:
- push eax
- mov al,73h
- jmp short cp_irq
- cp_irqc:
- push eax
- mov al,74h
- jmp short cp_irq
- cp_irqd:
- push eax
- mov al,75h
- jmp short cp_irq
- cp_irqe:
- push eax
- mov al,76h
- jmp short cp_irq
- cp_irqf:
- push eax
- mov al,77h
- ;─────────────────────────────────────────────────────────────────────────────
- cp_irq: ; main IRQ handler thingy
- mov [ss:cp_v86irqnum],al
- pop eax
- push ds
- push es
- push fs
- push gs
- pushfd
- push cs
- push D cp_irqpd
- pushad
- mov ax,10h
- mov ds,ax
- mov al,18h
- mov gs,ax
- mov al,[cp_v86irqnum]
- mov ebp,c_irqreal
- jmp [cp_v86irqintr]
- cp_irqpd:
- pop gs
- pop fs
- pop es
- pop ds
- iretd
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Custom get IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; Out:
- ; EDX - offset of IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- cp_getirqvect:
- push ebx
- pushfd
- cli
- movzx ebx,bl
- mov bl,[intslottbl+ebx]
- lea ebx,[ebx*8]
- add ebx,[cp_idt32ptr]
- mov dx,[ebx+6]
- shl edx,16
- mov dx,[ebx]
- popfd
- pop ebx
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Custom set IRQ handler offset
- ; In:
- ; BL - IRQ num (0-0fh)
- ; EDX - offset of IRQ handler
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- cp_setirqvect:
- push ebx
- push edx
- pushfd
- cli
- movzx ebx,bl
- mov bl,[intslottbl+ebx]
- lea ebx,[ebx*8]
- add ebx,[cp_idt32ptr]
- mov [ebx],dx
- shr edx,16
- mov [ebx+6],dx
- popfd
- pop edx
- pop ebx
- ret
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Custom set the base addx for a selector
- ; In:
- ; AX - selector
- ; EDX - linear base addx for selector
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- cp_setselector:
- push eax
- push edx
- movzx eax,ax
- and edx,0FFFFFFh
- or edx,92000000h
- mov [gdt32+eax+2],edx
- mov dl,[esp+3]
- mov [gdt32+eax+7],dl
- pop edx
- pop eax
- ret
-
- section stack stack align=16
- resb STAKSIZE*16
-