home *** CD-ROM | disk | FTP | other *** search
- ; PMODE v3.0 DPMI/VCPI/XMS/raw protected mode interface kernel.
- ; Copyright (c) 1994, Tran (a.k.a. Thomas Pytel).
-
- public _pm_selectors, _pm_pagetables, _pm_rmstacklen, _pm_rmstacks
- public _pm_callbacks, _pm_pmstacklen, _pm_pmstacks
- public _pm_info, _pm_init
-
- .386p
- locals
- PMODE_TEXT segment para public use16 'CODE'
- assume cs:PMODE_TEXT, ds:PMODE_TEXT
-
- off equ offset
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DATA
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- SELCODE = 08h ; PMODE_TEXT code selector
- SELZERO = 10h ; selector of entire memory space
- SELCALLBACKDS = 18h ; callback DS selector
- SELREAL = 20h ; real mode attributes selector
- SELVCPITSS = 28h ; TSS selector for VCPI
- SELVCPICODE = 30h ; VCPI call code selector
- SYSSELECTORS = 9 ; number of system selectors in GDT
-
- align 4
- dpmiepmode dd ? ; DPMI enter pmode addx
- codebase dd ? ; PMODE_TEXT linear address
- vcpistrucaddx dd off vcpi_cr3 ; VCPI switch structure linear address
- oldint15vector dd ? ; preserved INT 15h vector
-
- pmstacktop dd ? ; top of protected mode stack area
- pmstackbase dd ? ; bottom of protected mode stack area
- callbackbase dd ? ; base of real mode callbacks
- callbackseg dw ? ; segment of callbacks
-
- selzero dw SELZERO ; for immediate segreg loading
- selcallbackds dw SELCALLBACKDS ; for immediate segreg loading
-
- rawextmemused dw 1 ; raw extended memory used in K
- rawextmembase dd 0ffffffffh ; raw extended memory base
- rawextmemtop dd 0 ; raw extended memory top
-
- rmstackbase dw ? ; bottom of real mode stack area
- rmstacktop dw ? ; top of real mode stack area
- rmstackparmlen dw ? ; for functions 0300h, 0301h, 0302h
-
- gdtseg dw ? ; segment of GDT
-
- gdtlimit dw ? ; GDT limit |
- gdtbase dd ? ; GDT base |
- idtlimit dw 7ffh ; IDT limit |
- idtbase dd ? ; IDT base |
- rmidtlimit dw 3ffh ; real mode IDT limit |
- rmidtbase dd 0 ; real mode IDT base |
-
- rmtopmswrout dw off v_rmtopmsw ; addx of real to protected routine
- pmtormswrout dd off v_pmtormsw ; addx of protected to real routine
-
- pagetablebase dd ? ; base of page table area
- pagetabletop dd ? ; top of page table area
- pagetablenum db ? ; number of page tables
-
- _pm_pagetables db 1 ; number of page tables under VCPI
- _pm_selectors dw 64 ; max selectors under VCPI/XMS/raw
- _pm_rmstacklen dw 20h ; real mode stack length, in para
- _pm_pmstacklen dw 40h ; protected mode stack length, in para
- _pm_rmstacks db 4 ; real mode stack nesting
- _pm_pmstacks db 2 ; protected mode stack nesting
- _pm_callbacks db 16 ; number of real mode callbacks
- db ? ; for alignment
-
- pmstacklen dd ? ; protected mode stack length in bytes
-
- processortype db ? ; processor type |
- pmodetype db 2 ; protected mode type |
- picslave db 70h ; PIC slave base interrupt |
- picmaster db 8 ; PIC master base interrupt |
-
- tempd0 label dword ; temporary variables |
- tempw0 label word ; |
- tempb0 db ? ; |
- tempb1 db ? ; |
- tempw1 label word ; |
- tempb2 db ? ; |
- tempb3 db ? ; |
- tempd1 label dword ; |
- tempw2 label word ; |
- tempb4 db ? ; |
- tempb5 db ? ; |
- tempw3 label word ; |
- tempb6 db ? ; |
- tempb7 db ? ; |
-
- xms_callip dw ? ; XMS driver offset |
- xms_callcs dw ? ; XMS driver segment |
-
- vcpi_cr3 dd ? ; VCPI CR3 value for protected mode |
- vcpi_gdtaddx dd off gdtlimit ; linear addx of GDT limit and base |
- vcpi_idtaddx dd off idtlimit ; linear addx of IDT limit and base |
- vcpi_selldt dw 0 ; LDT selector for protected mode |
- vcpi_seltss dw SELVCPITSS ; TSS selector for protected mode |
- vcpi_eip dd off v_rmtopmswpm; destination EIP in protected mode |
- vcpi_cs dw SELCODE ; destination CS in protected mode |
-
- vcpi_calleip dd ? ; VCPI protected mode call offset |
- vcpi_callcs dw SELVCPICODE ; VCPI protected mode call selector |
-
- initrouttbl dw r_init, x_init, v_init, d_init
-
- int31functbl dw 0900h, 0901h, 0902h, 0000h, 0001h, 0003h, 0006h, 0007h
- dw 0008h, 0009h, 0200h, 0201h, 0204h, 0205h, 0305h, 0306h
- dw 0400h
- dw 000ah, 000bh, 000ch, 000eh, 000fh
- dw 0300h, 0301h, 0302h
- dw 0303h, 0304h
- dw 0500h, 0501h, 0502h, 0503h, 050ah
- INT31FUNCNUM = ($ - int31functbl) / 2
-
- int31routtbl dw int310900, int310901, int310902, int310000
- dw int310001, int310003, int310006, int310007
- dw int310008, int310009, int310200, int310201
- dw int310204, int310205, int310305, int310306
- dw int310400
- dw int31000a, int31000b, int31000c, int31000e, int31000f
- dw int310300, int310301, int310302
- dw int310303, int310304
- int31mrouttbl dw int310500v, int310501v, int310502v, int310503v
- dw int31050av
- int31mxrouttbl dw int310500x, int310501x, int310502x, int310503x
- dw int31050ax
- int31mrrouttbl dw int310500r, int310501r, int310502r, int310503r
- dw int31050ar
- int31mnrouttbl dw int310500rnomem, int31fail8013, int31fail8023
- dw int31fail8023, int31fail8023
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DETECT/INIT CODE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Get protected mode info
- ; Out:
- ; AX - return code:
- ; 0000h - successful
- ; 0001h - no 80386+ detected
- ; 0002h - system already in protected mode and no VCPI or DPMI found
- ; 0003h - DPMI - host is not 32bit
- ; CF - set on error, if no error:
- ; BX - number of paragraphs needed for protected mode data (may be 0)
- ; CL - processor type:
- ; 03h - 80386
- ; 04h - 80486
- ; 05h - 80586
- ; 06h-FFh - reserved for future use
- ; CH - protected mode type:
- ; 00h - raw
- ; 01h - XMS
- ; 02h - VCPI
- ; 03h - DPMI
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _pm_info:
- push dx si di ds es bx cx ; preserve registers
-
- push cs ; DS = CS (PMODE_TEXT)
- pop ds
-
- mov ax,1687h ; check for DPMI
- int 2fh
-
- or ax,ax ; DPMI present?
- jnz short @@infof0 ; if no, go on
-
- mov ax,3 ; error code in case DPMI not 32bit
- test bl,1 ; is DPMI 32bit?
- jz @@infofail ; if no, fail
-
- mov ax,1 ; error code in case no processor 386+
- cmp cl,3 ; is processor 386+?
- jb @@infofail ; if no, fail
-
- mov word ptr dpmiepmode[0],di ; store DPMI initial mode switch addx
- mov word ptr dpmiepmode[2],es
-
- mov bx,si ; BX = number of paragraphs needed
- mov ch,3 ; pmode type is 3 (DPMI)
-
- jmp @@infook ; go to done ok
-
- ;-----------------------------------------------------------------------------
- @@infof0:
- call detect_processor ; get processor type
-
- mov ax,1 ; error code in case no processor 386+
- cmp cl,3 ; is processor 386+?
- jb @@infofail ; if no, fail
-
- mov processortype,cl ; store processor type
-
- ;-----------------------------------------------------------------------------
- xor ax,ax ; get INT 67h vector
- mov es,ax
- mov ax,es:[67h*4]
- or ax,es:[67h*4+2] ; is vector NULL
- jz short @@infof2 ; if yes, no VCPI
-
- mov ax,0de00h ; call VCPI installation check
- int 67h
- or ah,ah ; AH returned as 0?
- jnz short @@infof2 ; if no, no VCPI
-
- movzx bx,_pm_pagetables ; BX = VCPI page table memory needed
- shl bx,8 ; 100h paragraphs per page table
- add bx,100h+0ffh+7+80h ; + page dir + align buf + TSS + IDT
-
- mov ch,2 ; pmode type is 2 (VCPI)
-
- jmp short @@infof1 ; go to figure other memory needed
-
- ;-----------------------------------------------------------------------------
- @@infof2:
- smsw ax ; AX = machine status word
- test al,1 ; is system in protected mode?
- mov ax,2 ; error code in case protected mode
- jnz short @@infofail ; if in protected mode, fail
-
- mov ax,4300h ; chek for XMS
- int 2fh
- cmp al,80h ; XMS present?
- sete ch ; if yes, pmode type is XMS
-
- mov bx,80h ; BX = memory requirement (IDT)
-
- ;-----------------------------------------------------------------------------
- @@infof1:
- movzx ax,_pm_rmstacks ; size of real mode stack area
- imul ax,_pm_rmstacklen
- add bx,ax
-
- movzx ax,_pm_pmstacks ; size of protected mode stack area
- imul ax,_pm_pmstacklen
- add bx,ax
-
- movzx ax,_pm_callbacks ; size of callbacks
- imul ax,25
- add ax,0fh
- shr ax,4
- add bx,ax
-
- mov ax,_pm_selectors ; size of GDT
- add ax,1+SYSSELECTORS+5
- shr ax,1
- add bx,ax
-
- jmp short @@infook ; go to done ok
-
- ;-----------------------------------------------------------------------------
- @@infofail:
- pop cx bx ; restore BX and CX
- stc ; carry set, failed
- jmp short @@infodone
-
- ;-----------------------------------------------------------------------------
- @@infook:
- mov pmodetype,ch ; store pmode type
-
- add sp,4 ; skip BX and CX on stack
- xor ax,ax ; success code, also clear carry flag
-
- ;-----------------------------------------------------------------------------
- @@infodone:
- pop es ds di si dx ; restore other registers
- retf ; return
-
- ;─────────────────────────────────────────────────────────────────────────────
- detect_processor: ; get processor: 386, 486, or 586
- xor cl,cl ; processor type 0 in case of exit
-
- pushf ; transfer FLAGS to BX
- pop bx
-
- mov ax,bx ; try to clear high 4 bits of FLAGS
- and ah,0fh
-
- push ax ; transfer AX to FLAGS
- popf
- pushf ; transfer FLAGS back to AX
- pop ax
-
- and ah,0f0h ; isolate high 4 bits
- cmp ah,0f0h
- je short @@detect_processordone ; if bits are set, CPU is 8086/8
-
- mov cl,2 ; processor type 2 in case of exit
-
- or bh,0f0h ; try to set high 4 bits of FLAGS
-
- push bx ; transfer BX to FLAGS
- popf
- pushf ; transfer FLAGS to AX
- pop ax
-
- and ah,0f0h ; isolate high 4 bits
- jz short @@detect_processordone ; if bits are not set, CPU is 80286
-
- inc cx ; processor type 3 in case of exit
-
- push eax ebx ; preserve 32bit registers
-
- pushfd ; transfer EFLAGS to EBX
- pop ebx
-
- mov eax,ebx ; try to flip AC bit in EFLAGS
- xor eax,40000h
-
- push eax ; transfer EAX to EFLAGS
- popfd
- pushfd ; transfer EFLAGS back to EAX
- pop eax
-
- xor eax,ebx ; AC bit fliped?
- jz short @@detect_processordone2; if no, CPU is 386
-
- inc cx ; processor type 3 in case of exit
-
- mov eax,ebx ; try to flip ID bit in EFLAGS
- xor eax,200000h
-
- push eax ; transfer EAX to EFLAGS
- popfd
- pushfd ; transfer EFLAGS back to EAX
- pop eax
-
- xor eax,ebx ; ID bit fliped?
- jz short @@detect_processordone2; if no, CPU is 486
-
- inc cx ; processor type 5, CPU is 586
-
- @@detect_processordone2:
- pop ebx eax ; restore 32bit registers
-
- @@detect_processordone:
- ret ; return
-
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- ; Initialize protected mode
- ; In:
- ; ES - real mode segment for protected mode data (ignored if not needed)
- ; Out:
- ; AX - return code:
- ; 0000h - successful
- ; 0001h - no 80386+ detected
- ; 0002h - system already in protected mode and no VCPI or DPMI found
- ; 0003h - DPMI - host is not 32bit
- ; 0004h - could not enable A20 gate
- ; 0005h - DPMI - could not enter 32bit protected mode
- ; 0006h - DPMI - could not allocate needed selectors
- ; CF - set on error, if no error:
- ; ESP - high word clear
- ; CS - 16bit selector for real mode CS with limit of 64k
- ; SS - selector for real mode SS with limit of 64k
- ; DS - selector for real mode DS with limit of 64k
- ; ES - selector for PSP with limit of 100h
- ; FS - 0 (NULL selector)
- ; GS - 0 (NULL selector)
- ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
- _pm_init:
- push bx cx ; get initial info on protected mode
- call far ptr _pm_info
- pop cx bx
- jnc short @@initf0 ; error?
-
- retf ; yup, abort
-
- @@initf0: ; no error, init protected mode
- pushad
- push ds
- mov bp,sp
- push cs ; DS = PMODE_TEXT
- pop ds
- cld
-
- mov eax,PMODE_TEXT ; set base addx of PMODE_TEXT
- shl eax,4
- mov codebase,eax
-
- movzx bx,pmodetype ; jump to appropriate init code
- shl bx,1
- jmp initrouttbl[bx]
-
- ;═════════════════════════════════════════════════════════════════════════════
- d_init: ; DPMI protected mode init
- pop ds ; get original caller DS from stack
- mov ax,1 ; enter DPMI protected mode
- call cs:dpmiepmode
- push ds ; put DS back onto stack
- jnc short dvxr_init ; error? if not, go on with init
-
- mov bx,6 ; error entering protected mode, set
- cmp ax,8011h ; error code and abort
- stc
- je short init_done
- mov bl,5 ; error code 5, not 6
-
- ;-----------------------------------------------------------------------------
- init_done: ; return with return code
- mov [bp+30],bx
- pop ds
- popad
- retf
-
- ;─────────────────────────────────────────────────────────────────────────────
- dvxr_init: ; DPMI/VCPI/XMS/raw common init tail
- mov bx,cs ; BX = CS if needed for same seg exit
- cmp word ptr [bp+36],PMODE_TEXT ; call came from same segment?
- je short @@dvxr_initdone ; if yes, done now
-
- xor ax,ax ; allocate selector for return code
- mov cx,1
- int 31h
- jnc short @@dvxr_initf0
-
- mov ah,4ch ; could not allocate selector
- int 21h ; terminate immediately
-
- @@dvxr_initf0:
- mov bx,ax ; new code descriptor for return
-
- mov ax,0007h ; set base address of calling segment
- xor cx,cx
- mov dx,[bp+36]
- shld cx,dx,4
- shl dx,4
- int 31h
-
- mov ax,0008h ; set selector limit of 64k
- xor cx,cx
- mov dx,0ffffh
- int 31h
-
- mov ax,0009h ; set selector type and access rights
- mov dx,cs ; get DPL from current CPL, and access
- lar cx,dx ; rights and type from current CS
- shr cx,8 ; type is already 16bit code segment
- int 31h
-
- @@dvxr_initdone:
- mov [bp+36],bx ; store selector in return address
- xor bx,bx ; init successful, carry clear
- jmp init_done
-
- ;═════════════════════════════════════════════════════════════════════════════
- v_init: ; VCPI protected mode init
- mov ax,0de0ah ; get PIC mappings
- int 67h
- mov picmaster,bl
- mov picslave,cl
-
- mov eax,codebase ; adjust addresses for VCPI structure
- add vcpi_gdtaddx,eax
- add vcpi_idtaddx,eax
- add vcpistrucaddx,eax
-
- mov dx,es ; align data area on page
- add dx,0ffh
- xor dl,dl
- mov es,dx
-
- movzx eax,dx ; set base and top of page table area
- shl eax,4
- add eax,1000h
- mov pagetablebase,eax
- movzx ecx,_pm_pagetables
- shl ecx,12
- add eax,ecx
- mov pagetabletop,eax
-
- xor di,di ; clear page dir and first page table
- mov cx,1000h
- xor ax,ax
- rep stosw
-
- mov gs,dx ; FS = segment of page directory
- lea eax,[edx+100h]
- mov es,ax ; ES = segment of first page table
- mov fs,ax ; GS = segment of first page table
-
- push ss ; stack space for VCPI descriptors
- pop ds
- sub sp,8*3
- mov si,sp
-
- xor di,di ; get VCPI protected mode interface
- mov ax,0de01h
- int 67h
-
- push cs ; DS = PMODE_TEXT
- pop ds
-
- mov vcpi_calleip,ebx ; store protected mode VCPI call EIP
- movzx si,dh ; get physical address of page dir
- shl si,2 ; from first page table for CR3
- lods dword ptr fs:[si]
- mov vcpi_cr3,eax
-
- @@v_initl0:
- and byte ptr es:[di+1],0f1h ; clear bits 9-11 in copied page table
- sub di,4
- jnc @@v_initl0
-
- mov dx,es ; DX = current page table segment
- xor ebx,ebx ; index in page dir, also loop counter
- jmp short @@v_initl1f0
-
- @@v_initl1:
- xor di,di ; clear page table
- mov cx,800h
- xor ax,ax
- rep stosw
-
- @@v_initl1f0:
- add dx,100h ; increment page table segment
- mov es,dx
-
- lods dword ptr fs:[si] ; set physical address of page table
- mov gs:[ebx*4],eax ; in page directory
-
- inc bx ; increment index in page directory
- cmp bl,_pm_pagetables ; at end of page tables?
- jb @@v_initl1 ; if no, loop
-
- ;-----------------------------------------------------------------------------
- push dx ; preserve seg of TSS for later use
-
- xor di,di ; clear TSS with all 0
- mov cx,34h
- xor ax,ax
- rep stosw
-
- mov eax,vcpi_cr3 ; set CR3 in TSS
- mov es:[1ch],eax
- mov dword ptr es:[66h],68h ; set offset of I/O permission bitmap
-
- add dx,7 ; increment next data area ptr
- mov es,dx
-
- ;─────────────────────────────────────────────────────────────────────────────
- vxr_init: ; VCPI/XMS/raw common init tail
- mov ax,es ; set IDT base address
- movzx ebx,ax
- shl ebx,4
- mov idtbase,ebx
-
- movzx bx,_pm_rmstacks ; set top and base of real mode stack
- imul bx,_pm_rmstacklen ; area for interrupt redirection
- add ax,80h ; from protected mode
- mov rmstackbase,ax
- add ax,bx
- mov rmstacktop,ax
-
- xor di,di ; set up IDT
- mov dx,word ptr picslave
- xor ecx,ecx
-
- @@vxr_initl0:
- lea eax,[SELCODE*10000h+ecx*4+off intrmatrix]
- stosd
-
- mov eax,8e00h ; interrupt gate type
- mov bl,cl ; isolate high 5 bits of int num
- and bl,0f8h
-
- test cl,0f8h ; one of the low 8 interrupts?
- jz short @@vxr_initl0f0 ; if yes, store as interrupt gate
-
- cmp bl,dl ; one of the high IRQs?
- je short @@vxr_initl0f0 ; if yes, store as interrupt gate
- cmp bl,dh ; one of the low IRQs?
- je short @@vxr_initl0f0 ; if yes, store as interrupt gate
-
- or ah,1 ; set to trap gate type
-
- @@vxr_initl0f0:
- stosd
-
- inc cl ; increment interrupt number
- jnz @@vxr_initl0 ; loop if more interrupts to go
-
- mov word ptr es:[8*31h],off int31 ; protected mode INT 31h
- mov word ptr es:[8*21h],off int21 ; protected mode INT 21h
-
- mov es,rmstacktop ; set next data area ptr to end of
- ; real mode stack area
- ;-----------------------------------------------------------------------------
- mov ax,es ; set protected mode stack area base
- movzx eax,ax ; for callbacks
- shl eax,4
- mov pmstackbase,eax
-
- movzx ecx,_pm_pmstacklen ; set protected mode stack area top
- movzx ebx,_pm_pmstacks ; for callbacks
- shl ecx,4
- mov pmstacklen,ecx ; protected mode stack size in bytes
- imul ebx,ecx
- add ebx,eax
- mov pmstacktop,ebx ; protected mode stack area top
-
- mov cl,_pm_callbacks ; CL = number of callbacks
- or cl,cl ; any callbacks?
- jz short @@vxr_initf3 ; if no, done with this part
-
- mov callbackbase,ebx ; top of stacks is base of callbacks
- shr ebx,4 ; BX = seg of callback area
- mov callbackseg,bx
-
- mov es,bx ; ES = seg of callback area
- xor di,di ; location within callback seg
-
- @@vxr_initl1:
- mov word ptr es:[di],6066h ; PUSHAD instruction
- mov byte ptr es:[di+2],068h ; PUSH WORD instruction
- mov word ptr es:[di+3],0 ; immediate 0 used as free flag
- mov word ptr es:[di+5],06866h ; PUSH DWORD instruction
- mov byte ptr es:[di+11],0b9h ; MOV CX,? instruction
- mov word ptr es:[di+14],06866h ; PUSH DWORD instruction
- mov byte ptr es:[di+20],0eah ; JMP FAR PTR ?:? intruction
- mov word ptr es:[di+21],off callback
- mov word ptr es:[di+23],PMODE_TEXT
-
- add di,25 ; increment ptr to callback
- dec cl ; decrement loop counter
- jnz @@vxr_initl1 ; if more callbacks to do, loop
-
- add di,0fh ; align next data area on paragraph
- shr di,4
- add bx,di
- mov es,bx ; set ES to base of next data area
-
- @@vxr_initf3:
-
- ;-----------------------------------------------------------------------------
- mov gdtseg,es ; store segment of GDT
-
- mov ax,es ; set GDT base address
- movzx eax,ax
- shl eax,4
- mov gdtbase,eax
-
- mov cx,_pm_selectors ; set GDT limit
- lea ecx,[8*ecx+8*5+8*SYSSELECTORS-1]
- mov gdtlimit,cx
-
- xor di,di ; clear GDT with all 0
- inc cx
- shr cx,1
- xor ax,ax
- rep stosw
-
- cmp pmodetype,2 ; if under VCPI, do VCPI GDT set up
- jne short @@vxr_initf1
-
- pop ax ; restore TSS seg from stack
- movzx eax,ax ; set up TSS selector in GDT
- shl eax,4
- mov dword ptr es:[SELVCPITSS+2],eax
- mov byte ptr es:[SELVCPITSS],67h
- mov byte ptr es:[SELVCPITSS+5],89h
-
- mov di,SELVCPICODE ; copy 3 VCPI descriptors from stack
- mov si,sp ; to GDT
- mov cx,4*3
- rep movs word ptr es:[di],word ptr ss:[si]
-
- add sp,8*3 ; adjust stack
-
- @@vxr_initf1:
- mov word ptr es:[SELZERO],0ffffh; set SELZERO descriptor
- mov word ptr es:[SELZERO+5],0df92h
-
- mov word ptr es:[SELCALLBACKDS],0ffffh ; set callback DS descriptor
- mov word ptr es:[SELCALLBACKDS+5],0df92h
-
- mov word ptr es:[SELREAL],0ffffh; set real mode attributes descriptor
- mov word ptr es:[SELREAL+5],01092h
-
- mov ax,cs ; set SELCODE descriptor (PMODE_TEXT)
- mov bx,SELCODE ; BX = index to SELCODE descriptor
- mov cx,0ffffh ; CX = limit (64k)
- mov dx,109ah ; DX = access rights
- call vxr_initsetdsc
-
- mov bx,8*SYSSELECTORS ; BX = base of free descriptors
- push bx ; store selector
-
- mov ax,ss ; set caller SS descriptor
- mov dx,5092h
- call vxr_initsetdsc
-
- mov ax,[bp] ; set caller DS descriptor
- mov [bp],bx ; put DS selector on stack for exit
- call vxr_initsetdsc
-
- push bx ; get PSP segment
- mov ah,51h
- int 21h
- mov si,bx
- pop bx
-
- mov fs,si ; set caller environment descriptor
- mov ax,fs:[2ch]
- or ax,ax ; is environment seg 0?
- jz short @@vxr_initf0 ; if yes, dont convert to descriptor
- mov fs:[2ch],bx ; store selector value in PSP
- call vxr_initsetdsc
-
- @@vxr_initf0:
- mov ax,si ; set caller PSP descriptor
- mov cx,0ffh ; limit is 100h bytes
- call vxr_initsetdsc
-
- ;-----------------------------------------------------------------------------
- lea ecx,[ebx-8] ; CX = ES descriptor, just set
- pop dx ; DX = SS descriptor, from stack
- mov ax,SELZERO ; AX = DS descriptor, SELZERO
- movzx ebx,sp ; EBX = SP, current SP - same stack
- mov si,SELCODE ; target CS is SELCODE, same segment
- mov edi,off @@vxr_initf2 ; target EIP
-
- jmp rmtopmswrout ; jump to mode switch routine
-
- @@vxr_initf2:
- mov edi,cs:codebase ; EDI = offset of PMODE_TEXT from 0
- mov eax,ds:[4*15h] ; get INT 15h vector
- mov ds:oldint15vector[edi],eax ; store INT 15h vector
-
- mov esi,cs:rawextmembase ; ESI = raw base of extended memory
- cmp esi,cs:rawextmemtop ; is there any raw extended memory?
- jae dvxr_init ; if no, go DPMI/VCPI/XMS/raw init
-
- dw 0b866h,off int15,PMODE_TEXT ; MOV EAX,PMODE_TEXT:offset int15
- mov ds:[4*15h],eax ; set new INT 15h handler
-
- mov edi,cs:rawextmemtop ; EDI = raw top of extended memory
- mov eax,edi ; EAX = size of extended memory
- sub eax,esi
- sub eax,10h ; subtract memory control block size
- mov [edi-16],eax ; store size in memory control block
- xor eax,eax
- mov [edi-12],eax ; no next memory control block
- mov [edi-8],eax ; no previous memory control block
- mov [edi-4],al ; memory block is free
-
- jmp dvxr_init ; go to DPMI/VCPI/XMS/raw init tail
-
- ;─────────────────────────────────────────────────────────────────────────────
- vxr_initsetdsc: ; set descriptor for VCPI/XMS/raw init
- movzx eax,ax ; EAX = base of segment
- shl eax,4
- mov word ptr es:[bx],cx ; limit = CX
- mov dword ptr es:[bx+2],eax ; base address = EAX
- mov word ptr es:[bx+5],dx ; access rights = DX
- add bx,8 ; increment descriptor index
- ret
-
- ;═════════════════════════════════════════════════════════════════════════════
- x_init: ; XMS protected mode init
- push es ; preserve ES, INT 2Fh destroys it
-
- mov ax,4310h ; get XMS driver address
- int 2fh
-
- mov xms_callip,bx ; store XMS driver address
- mov xms_callcs,es
-
- pop es ; restore ES (buffer segment)
-
- mov ah,3 ; enable A20
- call dword ptr xms_callip
-
- mov bx,4 ; error code 0004h in case of error
- cmp ax,1 ; error enabling A20?
- jc init_done ; if yes, exit with error 0004h
-
- mov si,off int31mxrouttbl ; set XMS memory allocation functions
-
- ;─────────────────────────────────────────────────────────────────────────────
- xr_init: ; XMS/raw common init tail
- push es ; preserve ES, INT 2Fh destroys it
-
- push ds ; ES = DS for table copy
- pop es
-
- mov di,off int31mrouttbl ; copy memory allocation function
- mov cx,5 ; addresses to table
- rep movsw
-
- pop es ; restore ES (buffer segment)
-
- mov rmtopmswrout,off xr_rmtopmsw; set XMS/raw mode switch addresses
- mov pmtormswrout,off xr_pmtormsw
-
- jmp vxr_init ; go to VCPI/XMS/raw continue init
-
- ;═════════════════════════════════════════════════════════════════════════════
- r_init: ; raw protected mode init
- mov ah,88h ; how much extended memory free
- int 15h
-
- mov si,off int31mnrouttbl ; SI -> no memory allocation functions
- or ax,ax ; if none, done with raw init
- jz xr_init
-
- movzx eax,ax ; convert AX K to ptr to top of mem
- shl eax,10
- add eax,100000h
- mov cs:rawextmemtop,eax
-
- call enablea20 ; enable A20
-
- push es ; preserve ES (buffer segment)
-
- xor cx,cx ; ES -> 0 (interrupt vector table)
- mov es,cx
- les bx,dword ptr es:[4*19h] ; ES:BX -> int vector table
-
- mov eax,100000h ; initial free extended memory base
- cmp dword ptr es:[bx+12h],'SIDV'; VDISK memory allocation?
- jne short @@r_initf0 ; if present, get base of free mem
-
- mov eax,dword ptr es:[bx+2ch] ; get first free byte of extended mem
- add eax,0fh ; align on paragraph
- and eax,0fffff0h ; address is only 24bit
-
- @@r_initf0:
- dec cx ; ES -> 0ffffh for ext mem addressing
- mov es,cx
-
- cmp dword ptr es:[13h],'SIDV' ; VDISK memory allocation?
- jne short @@r_initf1 ; if present, get base of free mem
-
- movzx ebx,word ptr es:[2eh] ; get first free K of extended memory
- shl ebx,10 ; adjust K to bytes
-
- cmp eax,ebx ; pick larger of 2 addresses
- ja short @@r_initf1
-
- mov eax,ebx
-
- @@r_initf1:
- pop es ; restore ES (buffer segment)
-
- mov si,off int31mnrouttbl ; SI -> no memory allocation functions
- cmp eax,cs:rawextmemtop ; any valid free extended memory
- jae xr_init ; if none, done with raw init
-
- mov cs:rawextmembase,eax
- mov si,off int31mrrouttbl ; set raw memory allocation functions
-
- jmp xr_init ; go to XMS/raw continue init
-
- ;─────────────────────────────────────────────────────────────────────────────
- enablea20: ; hardware enable gate A20
- pushf
- push fs gs
- cli
-
- xor ax,ax ; set A20 test segments 0 and 0ffffh
- mov fs,ax
- dec ax
- mov gs,ax
-
- call enablea20test ; is A20 already enabled?
- jz short @@enablea20done ; if yes, done
-
- in al,92h ; PS/2 A20 enable
- or al,2
- jmp short $+2
- jmp short $+2
- jmp short $+2
- out 92h,al
-
- call enablea20test ; is A20 enabled?
- jz short @@enablea20done ; if yes, done
-
- call enablea20kbwait ; AT A20 enable
- jnz short @@enablea20f0
-
- mov al,0d1h
- out 64h,al
-
- call enablea20kbwait
- jnz short @@enablea20f0
-
- mov al,0dfh
- out 60h,al
-
- call enablea20kbwait
-
- @@enablea20f0: ; wait for A20 to enable
- mov cx,800h ; do 800h tries
-
- @@enablea20l0:
- call enablea20test ; is A20 enabled?
- jz @@enablea20done ; if yes, done
-
- in al,40h ; get current tick counter
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,40h
- mov ah,al
-
- @@enablea20l1: ; wait a single tick
- in al,40h
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,40h
- cmp al,ah
- je @@enablea20l1
-
- loop @@enablea20l0 ; loop for another try
-
- mov bp,sp ; error, A20 did not enable
- mov ax,4 ; error code 4
- mov word ptr [bp+6],off init_done ; set init_done return address
-
- @@enablea20done:
- pop gs fs
- popf
- ret
-
- ;-----------------------------------------------------------------------------
- enablea20kbwait: ; wait for safe to write to 8042
- xor cx,cx
- @@enablea20kbwaitl0:
- jmp short $+2
- jmp short $+2
- jmp short $+2
- in al,64h ; read 8042 status
- test al,2 ; buffer full?
- loopnz @@enablea20kbwaitl0 ; if yes, loop
- ret
-
- ;-----------------------------------------------------------------------------
- enablea20test: ; test for enabled A20
- mov al,fs:[0] ; get byte from 0:0
- mov ah,al ; preserve old byte
- not al ; modify byte
- xchg al,gs:[10h] ; put modified byte to 0ffffh:10h
- cmp ah,fs:[0] ; set zero if byte at 0:0 not modified
- xchg al,gs:[10h] ; put back old byte at 0ffffh:10h
- ret ; return, zero if A20 enabled
-
- ;═════════════════════════════════════════════════════════════════════════════
- int15: ; real mode INT 15h handler
- cmp ah,88h ; function 88h?
- je short @@int15f0 ; if yes, need to process
-
- jmp cs:oldint15vector ; no, go on to old INT 15h handler
-
- @@int15f0:
- pushf ; call old int 15h handler
- call cs:oldint15vector
-
- sub ax,cs:rawextmemused ; adjust AX by extended memory used
-
- iret ; return with new AX extended memory
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; PROTECTED MODE KERNEL CODE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;═════════════════════════════════════════════════════════════════════════════
- v_rmtopmsw: ; VCPI real to protected switch
- pushf ; store FLAGS
- cli
- push cs ; DS = PMODE_TEXT
- pop ds
- pop tempw0 ; move FLAGS from stack to temp
- mov tempw1,ax ; store AX (protected mode DS)
- mov tempw2,si ; store SI (protected mode CS)
- mov esi,vcpistrucaddx ; ESI = linear addx of VCPI structure
- mov ax,0de0ch ; VCPI switch to protected mode
- int 67h
- v_rmtopmswpm:
- mov ss,dx ; load protected mode SS:ESP
- mov esp,ebx
- mov ds,cs:tempw1 ; load protected mode DS
- mov es,cx ; load protected mode ES
- xor ax,ax
- mov fs,ax ; load protected mode FS with NULL
- mov gs,ax ; load protected mode GS with NULL
- pushfd ; store EFLAGS
- mov ax,cs:tempw0 ; move bits 0-11 of old FLAGS onto
- and ah,0fh ; stack for IRETD
- and word ptr [esp],0f000h
- or [esp],ax
- push cs:tempd1 ; store protected mode target CS
- push edi ; store protected mode target EIP
- iretd ; go to targed addx in protected mode
-
- ;═════════════════════════════════════════════════════════════════════════════
- v_pmtormsw: ; VCPI protected to real switch
- pushf ; store FLAGS
- cli
- push ax ; store AX (real mode DS)
- mov ds,cs:selzero ; DS -> 0 (beginning of memory)
- movzx ebx,bx ; clear high word of EBX, real mode SP
- movzx edx,dx ; clear high word of EDX, real mode SS
- lea eax,[edx*4] ; EAX = linear ptr to top of real mode
- lea eax,[eax*4+ebx] ; stack
- mov dword ptr ds:[eax-4],0 ; store real mode GS
- mov dword ptr ds:[eax-8],0 ; store real mode FS
- movzx ecx,cx ; clear high word of ECX, real mode ES
- mov ds:[eax-16],ecx ; store real mode ES
- pop cx ; move real mode DS from protected
- mov ds:[eax-12],ecx ; mode stack to VCPI call stack
- mov ds:[eax-20],edx ; store real mode SS
- mov ds:[eax-24],ebx ; store real mode SP
- mov dword ptr ds:[eax-32],PMODE_TEXT ; store real mode CS
- mov dword ptr ds:[eax-36],off @@v_pmtormswf0 ; store real mode IP
- pop bx ; restore FLAGS from stack
- mov ss,cs:selzero ; SS -> 0 (beginning of memory)
- lea esp,[eax-4*9] ; ESP = stack ptr for VCPI call
- mov ax,0de0ch ; VCPI switch to real mode (V86)
- call fword ptr cs:vcpi_calleip
- @@v_pmtormswf0:
- push bx ; store old FLAGS
- push si ; store target CS in real mode
- push di ; store target IP in real mode
- iret ; go to target addx in real mode
-
- ;═════════════════════════════════════════════════════════════════════════════
- xr_rmtopmsw: ; XMS/raw real to protected switch
- pushfd ; store EFLAGS
- cli
- pop cs:tempd0 ; move EFLAGS from stack to temp
- mov cs:tempw2,ax ; store AX (protected mode DS)
- lidt fword ptr cs:idtlimit ; load protected mode IDT
- lgdt fword ptr cs:gdtlimit ; load protected mode GDT
- mov eax,cr0 ; switch to protected mode
- or al,1
- mov cr0,eax
- db 0eah ; JMP FAR PTR SELCODE:$+4
- dw $+4,SELCODE ; (clear prefetch que)
- mov ss,dx ; load protected mode SS:ESP
- mov esp,ebx
- mov ds,cs:tempw2 ; load protected mode DS
- mov es,cx ; load protected mode ES
- xor ax,ax
- mov fs,ax ; load protected mode FS with NULL
- mov gs,ax ; load protected mode GS with NULL
- pushf ; set NT=0 in current EFLAGS
- and byte ptr [esp+1],0bfh
- popf
- push cs:tempd0 ; store old EFLAGS
- and byte ptr [esp+1],0bfh ; set NT=0 in old EFLAGS
- push esi ; store protected mode target CS
- push edi ; store protected mode target EIP
- iretd ; go to targed addx in protected mode
-
- ;═════════════════════════════════════════════════════════════════════════════
- xr_pmtormsw: ; XMS/raw protected to real switch
- pushf ; store FLAGS
- cli
- push ax ; store AX (real mode DS)
- push cx ; store CX (real mode ES)
- mov ds,cs:selzero ; DS -> 0 (beginning of memory)
- mov ecx,cs:codebase ; get offset of PMODE_TEXT from 0
- pop ds:tempw0[ecx] ; move real mode ES from stack to temp
- pop ds:tempw1[ecx] ; move real mode DS from stack to temp
- pop ds:tempw2[ecx] ; move FLAGS from stack to temp
- mov ax,SELREAL ; load descriptors with real mode seg
- mov ds,ax ; attributes
- mov es,ax
- mov fs,ax
- mov gs,ax
- mov ss,ax ; load descriptor with real mode attr
- movzx esp,bx ; load real mode SP, high word 0
- lidt fword ptr cs:rmidtlimit ; load real mode IDT
- mov eax,cr0 ; switch to real mode
- and al,0feh
- mov cr0,eax
- db 0eah ; JMP FAR PTR PMODE_TEXT:$+4
- dw $+4,PMODE_TEXT ; (clear prefetch que)
- mov ss,dx ; load real mode SS
- mov ds,cs:tempw1 ; load real mode DS
- mov es,cs:tempw0 ; load real mode ES
- xor ax,ax
- mov fs,ax ; load real mode FS with NULL
- mov gs,ax ; load real mode GS with NULL
- push cs:tempw2 ; store old FLAGS
- push si ; store real mode target CS
- push di ; store real mode target IP
- iret ; go to target addx in real mode
-
- ;═════════════════════════════════════════════════════════════════════════════
- vxr_saverestorerm: ; VCPI/XMS/raw save/restore status
- retf ; no save/restore needed, 16bit RETF
-
- ;═════════════════════════════════════════════════════════════════════════════
- vxr_saverestorepm: ; VCPI/XMS/raw save/restore status
- db 66h,0cbh ; no save/restore needed, 32bit RETF
-
- ;═════════════════════════════════════════════════════════════════════════════
- critical_error: ; some unrecoverable error
- cli ; make sure we are not interrupted
- in al,61h ; beep
- or al,3
- out 61h,al
- jmp $ ; now hang
-
- ;═════════════════════════════════════════════════════════════════════════════
- callback: ; real mode callback handler
- mov ax,sp ; preserve SS:SP for callback
- push ss
- push ax
-
- push gs fs ds es ; preserve real mode regs for callback
- pushf ; preserve FLAGS for callback
-
- cli
- cld
-
- mov ebp,cs:pmstacktop ; EBP = ESP for protected mode
-
- mov ebx,ebp ; set EBX to next stack location
- sub ebx,cs:pmstacklen
- mov cs:pmstacktop,ebx ; update ptr for possible reenterancy
-
- cmp ebx,cs:pmstackbase ; exceeded protected mode stack space?
- jb critical_error ; if yes, critical error (hang)
-
- xor eax,eax ; EAX = base address of SS
- mov ax,ss
- shl eax,4
-
- movzx ebx,sp ; EBX = current linear SS:SP
- add ebx,eax
-
- mov es,cs:gdtseg ; set for protected mode callback DS
- or eax,92000000h ; base address in GDT
- mov es:[SELCALLBACKDS+2],eax
-
- mov ax,SELZERO ; DS selector for protected mode
- mov dx,ax ; SS selector = DS selector
- mov si,SELCODE ; target protected mode CS:EIP
- mov edi,offset @@callbackf0
-
- jmp cs:rmtopmswrout ; go to protected mode
-
- @@callbackf0:
- mov edi,[esp+14] ; EDI -> register structure from stack
-
- lea esi,[esp+24] ; copy general registers from stack
- mov ecx,8 ; to register structure
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
-
- mov esi,esp ; copy FLAGS, ES, DS, FG, and GS
- movs word ptr es:[edi],word ptr ds:[esi]
- movs dword ptr es:[edi],dword ptr ds:[esi]
- movs dword ptr es:[edi],dword ptr ds:[esi]
-
- lods dword ptr ds:[esi] ; EAX = real mode SS:SP from stack
- add ax,42 ; adjust SP for stuff on stack
- mov es:[edi+4],eax ; put in register structure
-
- mov ds,cs:selcallbackds ; DS = callback DS selector
- sub edi,42 ; EDI -> register structure
- movzx esi,ax ; ESI = old real mode SP
- xchg esp,ebp ; ESP = protected mode stack
-
- pushfd ; push flags for IRETD from callback
- db 66h ; push 32bit CS for IRETD
- push cs
- dw 6866h,@@callbackf1,0 ; push 32bit EIP for IRETD
-
- movzx eax,word ptr [ebp+22] ; EAX = target CS of callback
- push eax ; push 32bit CS for RETF to callback
- push dword ptr [ebp+18] ; push 32bit EIP for retf
-
- db 66h ; 32bit RETF to callback
- retf
-
- @@callbackf1:
- cli
- cld
-
- push es ; DS:ESI = register structure
- pop ds
- mov esi,edi
-
- mov es,cs:selzero ; ES -> 0 (beginning of memory)
-
- movzx ebx,word ptr [esi+2eh] ; EBX = real mode SP from structure
- movzx edx,word ptr [esi+30h] ; EDX = real mode SS from structure
- sub bx,42 ; subtract size of vars to be put
-
- mov ebp,[esi+0ch] ; EBP = pushed ESP from real mode
- mov bp,bx ; EBP = old high & new low word of ESP
-
- lea edi,[edx*4] ; EDI -> real mode base of stack
- lea edi,[edi*4+ebx] ; of vars to be stored
-
- mov ecx,8 ; copy general registers to stack
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
-
- mov eax,[esi+6] ; EAX = return FS and GS for real mode
- mov es:[edi],eax ; store on real mode stack for return
-
- mov ax,[esi] ; AX = return FLAGS for real mode
- mov es:[edi+8],ax ; store on real mode stack for return
- mov eax,[esi+10] ; EAX = return CS:IP for real mode
- mov es:[edi+4],eax ; store on real mode stack for return
-
- mov ax,[esi+4] ; AX = return DS for real mode
- mov cx,[esi+2] ; CX = return ES for real mode
-
- mov si,PMODE_TEXT ; real mode target CS:IP
- mov di,off @@callbackf2
-
- db 66h ; JMP DWORD PTR, as in 32bit offset,
- jmp word ptr cs:pmtormswrout ; not seg:16bit offset
-
- @@callbackf2:
- mov esp,ebp ; restore total ESP, old high word
-
- mov eax,cs:pmstacklen ; restore top of protected mode stack
- add cs:pmstacktop,eax
-
- popad ; get callback return general regs
- pop fs gs ; get callback return FS and GS values
- iret ; go to callback return CS:IP
-
- ;═════════════════════════════════════════════════════════════════════════════
- intrmatrix: ; INT redirectors for all INTs
- rept 100h
- call near ptr intr ; 3 byte CALL
- nop ; 1 byte NOP to align on 4
- endm
-
- ;═════════════════════════════════════════════════════════════════════════════
- intr: ; general interrupt redirector
- cli
- sub esp,2
- xchg eax,[esp] ; store EAX, also get CALL address
- push ecx edx ebx esp ebp esi edi; store rest of registers for POPAD
- push ds es fs gs
-
- mov ds,cs:selzero ; DS -> 0 (beginning of memory)
- mov edi,cs:codebase ; EDI = offset of PMODE_TEXT from 0
-
- mov dx,cs:rmstacktop ; DX = SS for real mode redirection
- movzx ebp,dx ; EBP -> top of real mode stack
- shl ebp,4
-
- mov bx,cs:_pm_rmstacklen ; get size of real mode stack
- sub dx,bx ; adjust DX to next stack location
- mov ds:rmstacktop[edi],dx ; update ptr for possible reenterancy
- shl bx,4 ; set real mode SP to top of stack
-
- cmp dx,cs:rmstackbase ; exceeded real mode stack space?
- jb critical_error ; if yes, critical error (hang)
-
- mov ds:[ebp-2],ss ; store SS:ESP on real mode stack
- mov ds:[ebp-6],esp
-
- shr eax,16 ; move CALL address to AX
- sub ax,off intrmatrix ; AX = int number, since AX is:
- shr ax,2 ; intrmatrix + (int number * 4)
-
- mov ah,al ; AH = high 5 bits of int number
- and ah,0f8h
-
- cmp ah,cs:picslave ; high IRQ?
- je short intrirq ; if yes, do IRQ
- cmp ah,cs:picmaster ; low IRQ?
- jne short intrint ; if no, do INT (with general regs)
-
- ;-----------------------------------------------------------------------------
- intrirq: ; an IRQ redirection
- mov ds:@@intrirqintnum[edi],al ; modify code with interrupt number
-
- mov si,PMODE_TEXT ; real mode target CS:IP
- mov di,off @@intrirqf0
- sub bx,6 ; adjust real mode SP for stored vars
-
- db 66h ; JMP DWORD PTR, as in 32bit offset,
- jmp word ptr cs:pmtormswrout ; not seg:16bit offset
-
- @@intrirqf0:
- db 0cdh ; INT @@intrirqintnum
- @@intrirqintnum db ?
-
- mov ax,SELZERO ; DS selector value for protected mode
- mov cx,ax ; ES selector value for protected mode
- pop ebx ; get protected mode SS:ESP from stack
- pop dx
- mov si,SELCODE ; target CS:EIP in protected mode
- mov edi,off @@intrirqf1
-
- jmp cs:rmtopmswrout ; go back to protected mode
-
- @@intrirqf1:
- mov edi,cs:codebase ; restore top of real mode stack
- mov ax,cs:_pm_rmstacklen
- add ds:rmstacktop[edi],ax
-
- pop gs fs es ds ; restore all registers
- popad
- iretd
-
- ;-----------------------------------------------------------------------------
- intrint: ; an INT redirection
- mov ds:@@intrintintnum[edi],al ; modify code with interrupt number
-
- mov es,cs:selzero ; copy registers from protected mode
- lea edi,[ebp-26h] ; stack to real mode stack
- lea esi,[esp+8]
- mov ecx,8
- cld
- rep movs dword ptr es:[edi],dword ptr ss:[esi]
-
- mov si,PMODE_TEXT ; real mode target CS:IP
- mov di,off @@intrintf0
- sub bx,26h ; adjust real mode SP for stored vars
-
- db 66h ; JMP DWORD PTR, as in 32bit offset,
- jmp word ptr cs:pmtormswrout ; not seg:16bit offset
-
- @@intrintf0:
- popad ; load regs with int call values
-
- db 0cdh ; INT @@intrirqintnum
- @@intrintintnum db ?
-
- pushad ; store registers on stack
- pushf ; store flags on stack
- cli
-
- xor eax,eax ; EAX = linear ptr to SS
- mov ax,ss
- shl eax,4
- movzx ebp,sp ; EBP = SP
-
- mov ebx,[bp+22h] ; get protected mode SS:ESP from stack
- mov dx,[bp+26h]
-
- add ebp,eax ; EBP -> stored regs on stack
-
- mov ax,SELZERO ; DS selector value for protected mode
- mov cx,ax ; ES selector value for protected mode
- mov si,SELCODE ; target CS:EIP in protected mode
- mov edi,off @@intrintf1
-
- jmp cs:rmtopmswrout ; go back to protected mode
-
- @@intrintf1:
- mov edi,cs:codebase ; restore top of real mode stack
- mov ax,cs:_pm_rmstacklen
- add ds:rmstacktop[edi],ax
-
- mov ax,ds:[ebp] ; move return FLAGS from real mode
- mov [esp+30h],ax ; stack to protected mode stack
-
- mov edi,ds:[ebp+2] ; restore return registers from real
- mov esi,ds:[ebp+6] ; mode stack
- mov ebx,ds:[ebp+18]
- mov edx,ds:[ebp+22]
- mov ecx,ds:[ebp+26]
- mov eax,ds:[ebp+30]
- mov ebp,ds:[ebp+10]
-
- pop gs fs es ds ; restore segment regs
- add esp,20h ; skip old general registers on stack
- iretd
-
- ;═════════════════════════════════════════════════════════════════════════════
- int21: ; watch for INT 21h AH=4Ch
- cmp ah,4ch ; AH = 4Ch?
- jne intrmatrix+4*21h ; if no, go to INT 21h redirection
-
- mov ds,cs:selzero ; DS -> 0 (beginning of memory)
- mov edi,cs:codebase ; EDI = offset of PMODE_TEXT from 0
-
- mov ebx,cs:oldint15vector ; put back old INT 15h handler
- mov ds:[4*15h],ebx
-
- jmp intrmatrix+4*21h ; go to INT 21h redirection
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; INT 31h INTERFACE
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;═════════════════════════════════════════════════════════════════════════════
- int31: ; protected mode INT 31h handler
- cli
- cld
- push ds es fs gs ; push regs needed
- pushad
- mov ds,cs:selzero ; DS -> 0 (beginning of memory)
-
- push bx
- mov bx,(INT31FUNCNUM - 1) * 2 ; number of functions to check
- @@int31l0:
- cmp ax,cs:int31functbl[bx] ; found function value?
- jne short @@int31l0c
-
- mov bx,cs:int31routtbl[bx] ; yes, go to appropriate handler
- xchg bx,[esp]
- ret
-
- @@int31l0c:
- sub bx,2 ; no, continue loop
- jnc @@int31l0
-
- pop bx ; no function found
- jmp int31fail8001 ; error 8001h
-
- ;-----------------------------------------------------------------------------
- int31fail8024: ; INT 31h return fail with error 8024h
- mov word ptr [esp+28],8024h ; set AX on stack to 8024h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8023: ; INT 31h return fail with error 8023h
- mov word ptr [esp+28],8023h ; set AX on stack to 8023h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8022: ; INT 31h return fail with error 8022h
- mov word ptr [esp+28],8022h ; set AX on stack to 8022h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8021: ; INT 31h return fail with error 8021h
- mov word ptr [esp+28],8021h ; set AX on stack to 8021h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8016: ; INT 31h return fail with error 8016h
- mov word ptr [esp+28],8016h ; set AX on stack to 8016h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8015: ; INT 31h return fail with error 8015h
- mov word ptr [esp+28],8015h ; set AX on stack to 8015h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8013: ; INT 31h return fail with error 8013h
- mov word ptr [esp+28],8013h ; set AX on stack to 8013h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8012: ; INT 31h return fail with error 8012h
- mov word ptr [esp+28],8012h ; set AX on stack to 8012h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8011: ; INT 31h return fail with error 8011h
- mov word ptr [esp+28],8011h ; set AX on stack to 8011h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8010: ; INT 31h return fail with error 8010h
- mov word ptr [esp+28],8010h ; set AX on stack to 8010h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31fail8001: ; INT 31h return fail with error 8001h
- mov word ptr [esp+28],8001h ; set AX on stack to 8001h for POPAD
- jmp short int31fail
-
- ;-----------------------------------------------------------------------------
- int31failcx: ; INT 31h return fail with CX,AX
- mov word ptr [esp+24],cx ; put CX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31failax: ; INT 31h return fail with AX
- mov word ptr [esp+28],ax ; put AX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31fail: ; INT 31h return fail, pop all regs
- popad
- pop gs fs es ds
-
- ;-----------------------------------------------------------------------------
- int31failnopop: ; INT 31h return fail with carry set
- or byte ptr [esp+8],1 ; set carry in EFLAGS on stack
- iretd
-
- ;-----------------------------------------------------------------------------
- int31okdx: ; INT 31h return ok with DX,CX,AX
- mov [esp+20],dx ; put CX onto stack for POPAD
- jmp short int31okcx
-
- ;-----------------------------------------------------------------------------
- int31oksinoax: ; INT 31h return ok SI,DI,BX,CX
- mov ax,[esp+28] ; get old value of AX for restore
-
- ;-----------------------------------------------------------------------------
- int31oksi: ; INT 31h return ok SI,DI,BX,CX,AX
- mov [esp+4],si ; put SI onto stack for POPAD
- mov [esp],di ; put DI onto stack for POPAD
- mov [esp+16],bx ; put BX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31okcx: ; INT 31h return ok with CX,AX
- mov [esp+24],cx ; put CX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31okax: ; INT 31h return ok with AX
- mov [esp+28],ax ; put AX onto stack for POPAD
-
- ;-----------------------------------------------------------------------------
- int31ok: ; INT 31h return ok, pop all regs
- popad
- pop gs fs es ds
-
- ;-----------------------------------------------------------------------------
- int31oknopop: ; INT 31h return ok with carry clear
- and byte ptr [esp+8],0feh ; clear carry in EFLAGS on stack
- iretd
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; DESCRIPTOR FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;-----------------------------------------------------------------------------
- int31testsel: ; test for valid selector BX
- pop bp ; pop return address
-
- cmp bx,cs:gdtlimit ; selector BX out of range?
- ja int31fail8022 ; if yes, fail with error 8022h
-
- mov edi,cs:gdtbase ; get base of GDT
- and bl,0f8h ; mask offset table index and RPL
- movzx ebx,bx ; EBX = selector index
- test byte ptr ds:[edi+ebx+6],10h; is descriptor used?
- jz int31fail8022 ; if descriptor not used, fail 8022h
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int31testaccess: ; test access bits in CX
- pop bp ; pop return address
-
- test ch,20h ; test MUST BE 0 bit in CH
- jnz int31fail8021 ; if not 0, error 8021h
-
- test cl,90h ; test present and MUST BE 1 bits
- jz int31fail8021 ; if both 0, error 8021h
- jpo int31fail8021 ; if unequal, error 8021h
-
- test cl,60h ; test DPL
- jnz int31fail8021 ; if not 0, error 8021h
-
- test cl,8 ; if code, more tests needed
- jz short @@int31testselok ; if data, skip code tests
-
- test cl,6 ; test conforming and readable bits
- jz int31fail8021 ; if both 0, error 8021h
- jpe int31fail8021 ; if equal, error 8021h
-
- @@int31testselok:
- jmp bp ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310000: ; allocate descriptors
- or cx,cx ; if CX = 0, error 8021h
- jz int31fail8021
-
- mov edx,cs:gdtbase ; get base of GDT
- movzx eax,cs:gdtlimit ; EAX = last selector index
- and al,0f8h
-
- mov bx,cx ; BX = number of selectors to find
- @@int310000l0:
- test byte ptr ds:[edx+eax+6],10h; is descriptor used?
- jnz short @@int310000l0f0
-
- dec bx ; found free descriptor, dec counter
- jnz short @@int310000l0f1 ; continue if need to find more
-
- mov ebx,eax ; found all descriptors requested
- @@int310000l1:
- mov dword ptr ds:[edx+ebx],0 ; set entire new descriptor
- mov dword ptr ds:[edx+ebx+4],109200h
- add bx,8 ; increment selector index
- dec cx ; dec counter of descriptors to mark
- jnz @@int310000l1 ; loop if more to mark
-
- jmp int31okax ; return ok, with AX
-
- @@int310000l0f0:
- mov bx,cx ; reset number of selectors to find
-
- @@int310000l0f1:
- sub ax,8 ; dec current selector counter
- cmp ax,8*SYSSELECTORS ; more descriptors to go?
- jae @@int310000l0 ; if yes, loop
-
- jmp int31fail8011 ; did not find descriptors
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310001: ; free descriptor
- call int31testsel ; test for valid selector BX
-
- and byte ptr ds:[edi+ebx+6],0efh; mark descriptor as free
-
- mov cx,4 ; zero any segregs loaded with BX
- lea ebp,[esp+32] ; EBP -> selectors on stack
- @@int310001l0:
- cmp word ptr [ebp],bx ; selector = BX?
- jne short @@int310001l0f0 ; if no, continue loop
-
- mov word ptr [ebp],0 ; zero selector on stack
-
- @@int310001l0f0:
- add ebp,2 ; increment selector ptr
- loop @@int310001l0 ; loop
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310003: ; get selector increment value
- mov ax,8 ; selector increment value is 8
- jmp int31okax ; return ok, with AX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310006: ; get segment base address
- call int31testsel ; test for valid selector BX
-
- mov dx,word ptr ds:[edi+ebx+2] ; low word of 32bit linear address
- mov cl,byte ptr ds:[edi+ebx+4] ; high word of 32bit linear address
- mov ch,byte ptr ds:[edi+ebx+7]
-
- jmp int31okdx ; return ok, with DX, CX, AX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310007: ; set segment base address
- call int31testsel ; test for valid selector BX
-
- mov word ptr ds:[edi+ebx+2],dx ; low word of 32bit linear address
- mov byte ptr ds:[edi+ebx+4],cl ; high word of 32bit linear address
- mov byte ptr ds:[edi+ebx+7],ch
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310008: ; set segment limit
- call int31testsel ; test for valid selector BX
-
- cmp cx,0fh ; limit greater than 1M?
- jbe short @@int310008f0
-
- mov ax,dx ; yup, limit greater than 1M
- and ax,0fffh
- cmp ax,0fffh ; low 12 bits set?
- jne int31fail8021 ; if no, error 8021h
-
- shrd dx,cx,12 ; DX = low 16 bits of page limit
- shr cx,12 ; CL = high 4 bits of page limit
- or cl,80h ; set granularity bit in CL
-
- @@int310008f0:
- mov word ptr ds:[edi+ebx],dx ; put low word of limit
- and byte ptr ds:[edi+ebx+6],70h ; mask off G and high nybble of limit
- or byte ptr ds:[edi+ebx+6],cl ; put high nybble of limit
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310009: ; set descriptor access rights
- call int31testsel ; test for valid selector BX
-
- call int31testaccess ; test access bits in CX
-
- or ch,10h ; set AVL bit, descriptor used
- and ch,0f0h ; mask off low nybble of CH
- and byte ptr ds:[edi+ebx+6],0fh ; mask off high nybble access rights
- or byte ptr ds:[edi+ebx+6],ch ; or in high access rights byte
- mov byte ptr ds:[edi+ebx+5],cl ; put low access rights byte
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31000a: ; create alias descriptor
- call int31testsel ; test for valid selector BX
-
- mov ax,0000h ; allocate descriptor
- mov cx,1
- int 31h
- jc int31fail8011 ; if failed, descriptor unavailable
-
- push ax ; preserve allocated selector
-
- push ds ; copy descriptor and set type data
- pop es
- movzx edi,ax ; EDI = target selector
- mov esi,cs:gdtbase ; ESI -> GDT
- add edi,esi ; adjust to target descriptor in GDT
- add esi,ebx ; adjust to source descriptor in GDT
-
- movs dword ptr es:[edi],dword ptr ds:[esi] ; copy descriptor
- lods dword ptr ds:[esi]
- mov ah,92h ; set descriptor type - R/W up data
- stos dword ptr es:[edi]
-
- pop ax ; restore allocated selector
-
- jmp int31okax ; return ok, with AX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31000b: ; get descriptor
- call int31testsel ; test for valid selector BX
-
- lea esi,[edi+ebx] ; ESI -> descriptor in GDT
- mov edi,[esp] ; get EDI buffer ptr from stack
- movs dword ptr es:[edi],dword ptr ds:[esi] ; copy descriptor
- movs dword ptr es:[edi],dword ptr ds:[esi]
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31000c: ; set descriptor
- call int31testsel ; test for valid selector BX
-
- mov esi,[esp] ; ESI = EDI buffer ptr from stack
- mov cx,es:[esi+5] ; get access rights from descriptor
- call int31testaccess ; test access bits in CX
-
- push ds ; swap DS and ES, target and source
- push es
- pop ds
- pop es
-
- add edi,ebx ; adjust EDI to descriptor in GDT
- movs dword ptr es:[edi],dword ptr ds:[esi] ; copy descriptor
- lods dword ptr ds:[esi]
- or eax,100000h ; set descriptor AVL bit
- stos dword ptr es:[edi]
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31000e: ; get multiple descriptors
- mov ax,000bh ; function 000bh, get descriptor
-
- ;-----------------------------------------------------------------------------
- int31000ef: ; common to funcions 000eh and 000fh
- or cx,cx ; if CX = 0, return ok immediately
- jz int31ok
-
- mov dx,cx ; DX = number of descriptors
- xor cx,cx ; CX = successful counter
- @@int31000efl0:
- mov bx,es:[edi] ; BX = selector to get
- add edi,2
-
- int 31h ; get/set descriptor
- jc int31failcx ; if error, fail with AX and CX
-
- add edi,8 ; increment descriptor ptr
- inc cx ; increment successful copy counter
- dec dx ; decrement loop counter
- jnz @@int31000efl0 ; if more descriptors to go, loop
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31000f: ; set multiple descriptors
- mov ax,000ch ; function 000ch, set descriptor
-
- jmp int31000ef ; go to common function
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; INTERRUPT FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310200: ; get real mode interrupt vector
- movzx ebx,bl ; EBX = BL (interrupt number)
- mov dx,ds:[ebx*4] ; load real mode vector offset
- mov cx,ds:[ebx*4+2] ; load real mode vector segment
-
- jmp int31okdx ; return ok, with AX, CX, DX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310201: ; set real mode interrupt vector
- movzx ebx,bl ; EBX = BL (interrupt number)
- mov ds:[ebx*4],dx ; set real mode vector offset
- mov ds:[ebx*4+2],cx ; set real mode vector segment
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310204: ; get protected mode interrupt vector
- movzx ebx,bl ; EBX = BL (interrupt number)
- shl ebx,3 ; adjust for location in IDT
- add ebx,cs:idtbase ; add base of IDT
-
- mov edx,dword ptr ds:[ebx+4] ; get high word of offset
- mov dx,word ptr ds:[ebx] ; get low word of offset
- mov cx,word ptr ds:[ebx+2] ; get selector
-
- jmp int31okdx ; return ok, with AX, CX, DX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310205: ; set protected mode interrupt vector
- xchg bx,cx ; swap int number with int selector
- call int31testsel ; test for valid selector BX
-
- movzx ecx,cl ; ECX = CL (interrupt number)
- shl ecx,3 ; adjust for location in IDT
- add ecx,cs:idtbase ; add base of IDT
-
- mov word ptr ds:[ecx],dx ; set low word of offset
- shr edx,16
- mov word ptr ds:[ecx+6],dx ; set high word of offset
- mov word ptr ds:[ecx+2],bx ; set selector
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310900: ; get and disable interrupt state
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- btc word ptr [esp+8],9 ; test and clear IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310901: ; get and enable interrupt state
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- bts word ptr [esp+8],9 ; test and set IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310902: ; get interrupt state
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- bt word ptr [esp+8],9 ; just test IF bit in EFLAGS
- setc al ; set AL = carry (IF flag from EFLAGS)
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; REAL/PROTECTED MODE TRANSLATION FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310300: ; simulate real mode interrupt
- movzx ebx,bl ; get real mode INT CS:IP
- mov ebp,dword ptr ds:[ebx*4]
-
- ;-----------------------------------------------------------------------------
- int31030012: ; common to 0300h, 0301h, and 0302h
- mov esi,cs:codebase ; ESI = offset of PMODE_TEXT from 0
-
- movzx ebx,word ptr es:[edi+2eh] ; EBX = SP from register structure
- movzx edx,word ptr es:[edi+30h] ; EDX = SS from register structure
-
- mov ax,bx ; check if caller provided stack
- or ax,dx
- jnz short @@int31030012f3 ; if yes, go on to set stack
-
- mov dx,cs:rmstacktop ; DX = SS for real mode redirection
- mov bx,cs:_pm_rmstacklen ; get size of real mode stack
- sub dx,bx ; adjust DX to next stack location
-
- cmp dx,cs:rmstackbase ; exceeded real mode stack space?
- jb int31fail8012 ; if yes, error 8012h
-
- mov ds:rmstacktop[esi],dx ; update ptr for possible reenterancy
- shl bx,4 ; adjust BX from paragraphs to bytes
-
- @@int31030012f3:
- lea edi,[edx*4] ; EDI -> top of real mode stack
- lea edi,[edi*4+ebx]
-
- movzx ax,byte ptr [esp+28] ; AX = AL of original INT 31h call
- and al,1 ; if function 0301h, AL=0, else, AL=2
- xor al,1
- shl al,1
- sub bx,ax ; adjust BX for possible FLAGS
-
- lea eax,[ecx*2] ; EAX = length of stack parms
-
- sub bx,ax ; adjust real mode SP for stored vars
- sub bx,36h
-
- xchg ax,ds:rmstackparmlen[esi] ; store length of stack parms, save
- push ax ; old value for possible reenterancy
-
- mov ds:[edi-2],ss ; store SS:ESP on real mode stack
- mov ds:[edi-6],esp
- mov ds:[edi-8],es ; store ES on real mode stack
-
- push ds ; swap DS and ES
- push es
- pop ds
- pop es
-
- std ; string copy backwards
-
- sub edi,10 ; copy stack parms from protected mode
- movzx ecx,cx ; stack to real mode stack
- lea esi,[esp+ecx*2+36h-2]
- rep movs word ptr es:[edi],word ptr ss:[esi]
-
- mov esi,[esp+2] ; ESI = offset of structure from stack
- mov ax,[esi+20h] ; AX = FLAGS from register structure
-
- mov es:[edi],ax ; store data for real mode return IRET
-
- cmp byte ptr [esp+30],1 ; check AL on stack for function code
- je short @@int31030012f4 ; if function 0301h, go on
-
- and ah,0fch ; 0300h or 0302h, clear IF and TF flag
-
- @@int31030012f4:
- cld ; string copy forward
- lea edi,[edx*4] ; EDI -> bottom of stack
- lea edi,[edi*4+ebx]
-
- mov ecx,8 ; copy general regs to real mode stack
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
-
- add esi,6 ; copy FS and GS to real mode stack
- movs dword ptr es:[edi],dword ptr ds:[esi]
-
- mov word ptr es:[edi+8],PMODE_TEXT ; return address from call
- mov word ptr es:[edi+6],off @@int31030012f1
-
- mov es:[edi+4],ax ; store FLAGS for real mode IRET maybe
- mov dword ptr es:[edi],ebp ; put call address to real mode stack
-
- mov ax,[esi-6] ; real mode DS from register structure
- mov cx,[esi-8] ; real mode ES from register structure
-
- mov si,PMODE_TEXT ; real mode target CS:IP
- mov di,off @@int31030012f0
-
- db 66h ; JMP DWORD PTR, as in 32bit offset,
- jmp word ptr cs:pmtormswrout ; not seg:16bit offset
-
- @@int31030012f0: ; real mode INT, FAR, or IRET call
- popad ; load regs with call values
- pop fs gs
-
- iret ; go to call address
-
- @@int31030012f1:
- add sp,cs:rmstackparmlen ; remove stack parameters
-
- push gs fs ds es ; store registers on stack
- pushf ; store flags on stack
- pushad
- cli
-
- mov ax,ss ; EAX = linear ptr to SS
- movzx eax,ax
- shl eax,4
- movzx ebp,sp ; EBP = SP
-
- mov cx,[bp+2ah] ; get protected mode ES from stack
- mov ebx,[bp+2ch] ; get protected mode SS:ESP from stack
- mov dx,[bp+30h]
-
- add ebp,eax ; EBP -> stored regs on stack
-
- mov ax,SELZERO ; DS selector value for protected mode
- mov si,SELCODE ; target CS:EIP in protected mode
- mov edi,off @@int31030012f2
-
- jmp cs:rmtopmswrout ; go back to protected mode
-
- @@int31030012f2:
- mov edi,cs:codebase ; restore old stack parameter length
- pop ds:rmstackparmlen[edi]
-
- mov edi,[esp] ; get structure offset from stack
- mov esi,ebp ; copy return regs from real mode
- mov ecx,15h ; stack to register structure
- cld
- rep movs word ptr es:[edi],word ptr ds:[esi]
-
- cmp dword ptr es:[edi+4],0 ; stack provided by caller?
- jne int31ok ; if yes, done now
-
- mov edi,cs:codebase ; restore top of real mode stack
- mov ax,cs:_pm_rmstacklen
- add ds:rmstacktop[edi],ax
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310301: ; call real mode FAR procedure
- ; same start as function 0302h
- ;─────────────────────────────────────────────────────────────────────────────
- int310302: ; call real mode IRET procedure
- mov ebp,dword ptr es:[edi+2ah] ; get target CS:IP from structure
- jmp int31030012 ; go to common code
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310303: ; allocate real mode callback address
- mov bl,cs:_pm_callbacks ; CL = total number of callbacks
- or bl,bl ; are there any?
- jz int31fail8015 ; if no, error 8015h
-
- mov edx,cs:callbackbase ; EDX -> base of callbacks
- mov ecx,edx ; for later use
-
- @@int310303l0:
- cmp word ptr [edx+3],0 ; is this callback free?
- jz short @@int310303f0 ; if yes, allocate
-
- add edx,25 ; increment ptr to callback
- dec bl ; decrement loop counter
- jnz @@int310303l0 ; if more callbacks to check, loop
-
- jmp int31fail8015 ; no free callback, error 8015h
-
- @@int310303f0:
- mov bx,[esp+38] ; BX = caller DS from stack
- mov [edx+3],bx ; store callback parms in callback
- mov [edx+7],esi
- mov [edx+12],es
- mov [edx+16],edi
-
- sub edx,ecx ; DX = offset of callback
- shr ecx,4 ; CX = segment of callback
-
- jmp int31okdx ; return ok, with DX, CX, AX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310304: ; free real mode callback address
- cmp cx,cs:callbackseg ; valid callback segment?
- jne int31fail8024 ; if no, error 8024h
-
- movzx ebx,dx ; EBX = offset of callback
-
- xor ax,ax ; check if valid offset
- xchg dx,ax
- mov cx,25
- div cx
-
- or dx,dx ; is there a remainder
- jnz int31fail8024 ; if yes, not valid, error 8024h
-
- or ah,ah ; callback index too big?
- jnz int31fail8024 ; if yes, not valid, error 8024h
-
- cmp al,cs:_pm_callbacks ; callback index out of range?
- jae int31fail8024 ; if yes, not valid, error 8024h
-
- add ebx,cs:callbackbase ; EBX -> callback
- mov word ptr [ebx+3],0 ; set callback as free
-
- jmp int31ok ; return ok
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; MISC FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310305: ; get state save/restore addresses
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- xor ax,ax ; size needed is none
- mov bx,PMODE_TEXT ; real mode seg of same RETF
- mov cx,off vxr_saverestorerm ; same offset of 16bit RETF
- mov si,cs ; selector of routine is this one
- mov edi,off vxr_saverestorepm ; offset of simple 32bit RETF
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310306: ; get raw mode switch addresses
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- mov si,cs ; selector of pmtorm rout is this one
- mov edi,cs:pmtormswrout ; offset in this seg of rout
- mov bx,PMODE_TEXT ; real mode seg of rmtopm rout
- mov cx,cs:rmtopmswrout ; offset of rout in real mode
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310400: ; get version
- add esp,26h ; adjust stack
- pop ds ; restore DS
-
- mov ax,100h ; return version 1.0
- mov bx,3 ; capabilities
- mov cl,cs:processortype ; processor type
- mov dx,word ptr cs:picslave ; master and slave PIC values
-
- jmp int31oknopop ; return ok, dont pop registers
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; VCPI EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;-----------------------------------------------------------------------------
- int310500vsiditoesi: ; convert handle SI:DI to ptr ESI
- pop bp ; pop return address
-
- test di,3 ; is handle (ptr) aligned on dword?
- jnz int31fail8023 ; if no, error 8023h
-
- shl esi,16 ; ESI = SI:DI
- mov si,di
-
- cmp esi,cs:pagetablebase ; handle too low?
- jb int31fail8023 ; if yes, error 8023h
-
- cmp esi,cs:pagetabletop ; handle too high?
- jae int31fail8023 ; if yes, error 8023h
-
- test byte ptr [esi+1],2 ; is page first in allocated block?
- jz int31fail8023 ; if no, error 8023h
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500vbxcxtoebx: ; convert BX:CX bytes to EBX pages
- pop bp ; pop return address
-
- shl ebx,16 ; EBX = BX:CX
- mov bx,cx
-
- or ebx,ebx ; check for invalid value
- jz int31fail8021 ; if invalid value, error 8021h
-
- add ebx,0fffh ; convert EBX to page count
- shr ebx,12
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500vpmalloc: ; allocate physical memory block
- mov edi,esi ; EDI = ESI, ptr to linear block start
- xor ebp,ebp ; EBP = running allocated page count
-
- @@int310500vpmallocl0:
- mov ax,0de04h ; VCPI allocate a page
- call fword ptr cs:vcpi_calleip
-
- or ah,ah ; got a page?
- jz short @@int310500vpmallocl0f0; if yes, go on
-
- cmp ebp,1 ; allocated any pages?
- jc short @@int310500vpmallocdone; if no, fail immediately
-
- or byte ptr [edi-3],4 ; set last allocated page as last
-
- call int310500vfree ; free what was allocated
-
- stc ; carry set, failed
- jmp short @@int310500vpmallocdone ; go to done
-
- @@int310500vpmallocl0f0:
- or dl,7 ; set page as user/writeable/present
- mov [edi],edx ; store page in page table
- add edi,4 ; increment page table ptr
-
- inc ebp ; increment allocated page count
- cmp ebp,ebx ; allocated all needed pages?
- jb @@int310500vpmallocl0 ; if no, loop
-
- or byte ptr [esi+1],2 ; set first allocated page as first
- or byte ptr [edi-3],4 ; set last allocated page as last
- clc ; carry clear, success
-
- @@int310500vpmallocdone:
- mov eax,ebp ; EAX = number of pages allocated
- ret ; return
-
- ;-----------------------------------------------------------------------------
- int310500vlmalloc: ; check for linear memory block
- mov edi,cs:pagetablebase ; EDI = search ptr in page table
-
- mov ecx,cs:pagetabletop ; ECX = count of pages to search
- sub ecx,edi
- shr ecx,2
-
- xor edx,edx ; EDX = largest linear block found
- xor eax,eax ; EAX = search unit, free entry (0)
-
- push ebx ; preserve EBX, memory requested
-
- @@int310500vlmallocl0:
- jecxz short @@int310500vlmallocdone ; if no more entries, done
-
- repne scas dword ptr es:[edi] ; search for first next free entry
- jne short @@int310500vlmallocdone ; if no more free, go on
-
- mov ebp,ecx ; EBP = current count
- lea ebx,[edi-4] ; EBX = start of free block
-
- repe scas dword ptr es:[edi] ; search for end of free linear block
- jne short @@int310500vlmallocl0f0; if previous entry not free, go on
-
- inc ebp ; previous entry free, extra one
-
- @@int310500vlmallocl0f0:
- sub ebp,ecx ; EBP = number of free pages in block
-
- cmp ebp,edx ; new block larger than last largest?
- jb @@int310500vlmallocl0 ; if no, loop
-
- mov esi,ebx ; ESI = ptr to largest block found
- mov edx,ebp ; size of new largest block found
-
- cmp ebp,[esp] ; block sufficient for memory request?
- jb @@int310500vlmallocl0 ; if no, loop
-
- @@int310500vlmallocdone:
- pop ebx ; restore EBX, memory requested
- ret ; return
-
- ;-----------------------------------------------------------------------------
- int310500vmalloc: ; allocate linear+physical mem block
- call int310500vlmalloc ; try to allocate linear memory block
-
- cmp edx,1 ; found ANY free linear area?
- jc short @@int310500vmallocdone ; if no, done
-
- cmp edx,ebx ; linear block enough for request?
- jb short @@int310500vmallocf0 ; if no, go to physical memory check
-
- call int310500vpmalloc ; try to allocate physical mem
-
- mov cl,1 ; error is not enough physical memory
- jmp short @@int310500vmallocdone; go to done
-
- @@int310500vmallocf0:
- mov ebx,edx ; only linear block size physical mem
-
- call int310500vpmalloc ; try to allocate physical memory
- jc short @@int310500vmallocfaillinear ; if failed, done
-
- call int310500vfree ; success, so must free block
-
- mov eax,ebx ; can allocate this much total memory
- stc ; carry set, failed
-
- @@int310500vmallocfaillinear:
- mov cl,0 ; error is not enough linear memory
-
- @@int310500vmallocdone:
- ret ; return
-
- ;-----------------------------------------------------------------------------
- int310500vfree: ; free linear+physical memory block
- mov edi,esi ; EDI = ESI, ptr to linear block start
-
- @@int310500vfreel0:
- xor ecx,ecx ; new page table entry is free (0)
- xchg ecx,[edi] ; swap ECX with page table entry
- add edi,4 ; increment page table ptr
-
- mov edx,ecx ; EDX = page table entry
- and dx,0f000h ; mask off low 12 bits
-
- mov ax,0de05h ; VCPI free a page
- call fword ptr cs:vcpi_calleip
-
- test ch,4 ; last page of block?
- jz @@int310500vfreel0 ; if no, loop
-
- ret ; return
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310500v: ; VCPI get free memory information
- push ds ; ES = DS for VCPI malloc functions
- pop es
-
- mov ebx,0ffffffffh ; try to allocate an impossible amount
- call int310500vmalloc
-
- shl eax,12 ; returned EAX is highest possible
-
- jmp int310500xsetbuf ; put memory information in buffer
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310501v: ; VCPI allocate memory block
- push ds ; ES = DS for VCPI malloc functions
- pop es
-
- call int310500vbxcxtoebx ; convert BX:CX bytes to EBX pages
-
- call int310500vmalloc ; try to allocate requested amount
- jnc short int310501vaddxnhandle ; if successful, go to done
-
- or cl,cl ; error is not enough linear memory?
- jz int31fail8012 ; if yes, error 8013h
- jmp int31fail8013 ; error is physical, error 8013h
-
- int310501vaddxnhandle:
- mov ecx,esi ; figure address of block from handle
- sub ecx,cs:pagetablebase
- shl ecx,10
- shld ebx,ecx,16
-
- mov di,si ; SI:DI = ESI, handle
- shr esi,16
-
- mov eax,cs:vcpi_cr3 ; reload CR3 to clear TLB
- mov cr3,eax
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310502v: ; VCPI free memory block
- call int310500vsiditoesi ; convert handle SI:DI to ptr ESI
-
- call int310500vfree ; free memory block
-
- mov eax,cs:vcpi_cr3 ; reload CR3 to clear TLB
- mov cr3,eax
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310503v: ; VCPI resize memory block
- push ds ; ES = DS for VCPI malloc functions
- pop es
-
- call int310500vbxcxtoebx ; convert BX:CX bytes to EBX pages
-
- call int310500vsiditoesi ; convert handle SI:DI to ptr ESI
-
- mov edi,esi ; EDI = ESI, ptr to linear block start
- xor ebp,ebp ; EBP = running block size in pages
-
- @@int310503vl0:
- add edi,4 ; increment page table ptr
- inc ebp ; increment block size
-
- test byte ptr [edi-3],4 ; last page of block?
- jz @@int310503vl0 ; if no, loop
-
- sub ebx,ebp ; EBX = change in block size
- jz int310501vaddxnhandle ; if no change, done
-
- jc @@int310503vf0 ; if block made smaller, just free top
-
- mov ecx,cs:pagetabletop ; ECX = count of pages to search
- sub ecx,edi
- shr ecx,2
-
- mov edx,ecx ; EDX = current count
- xor eax,eax ; EAX = search unit, free entry (0)
-
- jecxz short @@int310503vf3 ; if no entries above, try below
-
- repe scas dword ptr es:[edi] ; check for free entries above block
- je short @@int310503vf2 ; if previous entry free, go on
-
- dec edx ; previous entry not free, minus one
-
- @@int310503vf2:
- sub edx,ecx ; EDX = number of free pages in block
-
- cmp edx,ebx ; enough linear memory?
- jb short @@int310503vf3 ; if no, try below in linear memory
-
- push esi ; preserve start of block
- lea esi,[esi+ebp*4] ; ESI -> start of new block for alloc
-
- call int310500vpmalloc ; try to allocate physical memory
- mov edi,esi ; EDI -> start of new block
- pop esi ; restore start of old block
- jc int31fail8013 ; if alloc failed, error 8013h
-
- and byte ptr [edi-3],0fbh ; clear last bit in old block end
- and byte ptr [edi+1],0fdh ; clear first bit in new block start
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf3:
- mov ecx,esi ; ECX = count of pages to search up
- sub ecx,cs:pagetablebase
- shr ecx,2
-
- or ecx,ecx ; any linear memory below?
- jz @@int310503vf1 ; if no, try to allocate
-
- push ebp ; preserve size of original block
-
- lea edi,[esi-4] ; EDI = ESI, ptr to linear block start
- mov ebp,ecx ; EBP = current count
-
- std ; search is up
- repe scas dword ptr es:[edi] ; check for free entries after block
- cld
- je short @@int310503vf4 ; if previous entry free, go on
-
- dec ebp ; previous entry not free, minus one
-
- @@int310503vf4:
- sub ebp,ecx ; EBP = number of free pages in block
- lea eax,[ebp+edx] ; free size below + free size above
-
- pop ebp ; restore original block size
-
- cmp eax,ebx ; enough linear memory?
- jb @@int310503vf1 ; if no, try to allocate
-
- push esi ; preserve original block address
-
- sub ebx,edx ; EBX = number of pages needed below
- lea eax,[ebx*4] ; get base of block below
- sub esi,eax
-
- push edx ebp ; preserve some vars
- call int310500vpmalloc ; try to allocate physical memory
- pop ebp edx ; restore some vars
-
- mov edi,esi ; EDI -> base of block below
- pop esi ; restore base of original block
- jc int31fail8013 ; if alloc failed, error 8013h
-
- or edx,edx ; any pages needed above?
- jz short @@int310503vf6 ; if no, go on
-
- push esi edi ebp ; preserve some vars
-
- mov ebx,edx ; EBX = size of block below
- lea esi,[esi+ebp*4] ; ESI -> start of block above
-
- call int310500vpmalloc ; try to allocate physical memory
- pop ebp edi esi ; restore some vars
- jnc short @@int310503vf5 ; if allocated ok, go on
-
- mov esi,edi ; ESI -> allocated block below
- call int310500vfree ; free allocated block below
-
- jmp int31fail8013 ; fail, error 8013h
-
- @@int310503vf5:
- and byte ptr [esi-3],0fbh ; clear last bit in below block end
- and byte ptr [esi+ebp*4+1],0fdh ; clear first bit in above block start
-
- @@int310503vf6:
- and byte ptr [edi+1],0fdh ; clear first bit in below block start
- and byte ptr [esi+ebp*4-3],0fbh ; clear last bit in old block end
-
- push edi ; preserve new block start
-
- mov edx,edi ; EDX = base of move area
- lea ebx,[esi-4] ; EBX = current location in move area
-
- @@int310503vl1:
- mov edi,ebx ; set up to shift up a page
- mov esi,ebx
- mov ecx,ebp
-
- lods dword ptr ds:[esi] ; shift old pages a page down in table
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
- stos dword ptr es:[edi]
-
- sub ebx,4 ; decrement to next page to shift
- cmp ebx,edx ; more pages to shift?
- jae @@int310503vl1 ; if yes, loop
-
- pop esi ; restore new block start address
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf1:
- add ebx,ebp ; restore EBX as requested size
-
- push esi ebp ; preserve some vars
- call int310500vlmalloc ; check for linear memory block
- pop ebp edi ; restore some vars
-
- cmp edx,ebx ; enough linear memory?
- jb int31fail8012 ; if no, error 8012h
-
- sub ebx,ebp ; EBX = extra pages needed
- push esi ; preserve for later copy
- lea esi,[esi+ebp*4] ; ESI -> start of extra space needed
-
- push edi ebp ; preserve some vars
- call int310500vpmalloc ; try to allocate physical memory
- pop ecx esi edi ; restore some vars
- jc int31fail8013 ; if not enough mem, error 8013h
-
- push edi esi ecx ; preserve, new and old block, size
-
- rep movs dword ptr es:[edi],dword ptr ds:[esi] ; copy old block pages
-
- and byte ptr [edi-3],0fbh ; clear last bit in old block end
- and byte ptr [edi+1],0fdh ; clear first bit in new block start
-
- pop ecx edi ; restore to clear old block
-
- xor eax,eax ; new page table entry is free (0)
- rep stos dword ptr es:[edi] ; clear old page table block
-
- pop esi ; restore new block address
-
- jmp int310501vaddxnhandle ; go to done
-
- @@int310503vf0:
- sub edi,4 ; decrement page table ptr
-
- xor edx,edx ; new page table entry is free (0)
- xchg edx,[edi] ; swap EDX with page table entry
- and dx,0f000h ; mask off low 12 bits
-
- mov ax,0de05h ; VCPI free a page
- call fword ptr cs:vcpi_calleip
-
- inc ebx ; increment negative change counter
- jnz @@int310503vf0 ; if more pages to free, loop
-
- or byte ptr [edi-3],4 ; set next page up as last of block
-
- jmp int310501vaddxnhandle ; go to done
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31050av: ; VCPI get memory block size and base
- shrd ecx,esi,16 ; figure address of block from handle
- mov cx,di
- sub ecx,cs:pagetablebase
- shl ecx,10
- shld ebx,ecx,16
-
- call int310500vsiditoesi ; convert handle SI:DI to ptr ESI
-
- xor edi,edi ; EDI = running page count
-
- @@int31050avl0:
- inc edi ; increment page count
-
- lods dword ptr ds:[esi] ; EAX = page table entry
- test ah,4 ; is this the last page of the block?
- jz @@int31050avl0 ; if no, loop
-
- shl edi,12 ; convert EDI pages to bytes
- shld esi,edi,16 ; SI:DI = EDI, size in bytes
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; XMS EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;-----------------------------------------------------------------------------
- int310500xsetbuf:
- mov es,[esp+24h] ; get ES:EDI buffer ptr from stack
- mov edi,[esp]
-
- stos dword ptr es:[edi] ; store block size in output buffer
- mov ecx,0bh ; fill rest of buffer with 0ffffffffh
- mov eax,0ffffffffh
- rep stos dword ptr es:[edi]
-
- jmp int31ok ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500xcallxms: ; make a all to real mode XMS driver
- pop bp ; pop return address
- sub esp,32h ; stack space for register structure
-
- mov [esp+1ch],ax ; put AX in register structure
- mov [esp+10h],bx ; put BX in register structure
- mov [esp+18h],cx ; put CX in register structure
- mov [esp+14h],dx ; put DX in register structure
-
- mov word ptr [esp+20h],0 ; zero FLAGS in register structure
- mov dword ptr [esp+2eh],0 ; zero SS:SP in register structure
- mov eax,dword ptr cs:xms_callip ; put XMS driver address in CS:IP in
- mov [esp+2ah],eax ; regis]er structure
-
- push ss ; ES:EDI -> register structure
- pop es
- mov edi,esp
-
- xor cx,cx ; copy 0 words as stack parameters
- xor bh,bh ; doesnt really need to be here
- mov ax,301h ; call real mode FAR procedure
- int 31h
-
- mov ax,[esp+1ch] ; get AX from register structure
- mov bx,[esp+10h] ; get BX from register structure
- mov cx,[esp+18h] ; get CX from register structure
- mov dx,[esp+14h] ; get DX from register structure
-
- lea esp,[esp+32h] ; adjust ESP without changing FLAGS
- jc int31fail8010 ; if INT 31h failed, error 8010h
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500xbxcxtodx: ; convert BX:CX bytes to DX K
- pop bp ; pop return address
-
- mov dx,cx ; check for invalid value, BX=CX=0
- or dx,bx
- jz int31fail8021 ; if invalid value, error 8021h
-
- add cx,1023+15 ; adjust for size in K and align
- adc bx,0
-
- test bh,0fch ; memory request too high
- jnz int31fail8013 ; if yes, error 8013h
-
- shrd cx,bx,10 ; CX = memory in K
- mov dx,cx
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500xerror: ; XMS error, return with DPMI error
- cmp bl,0a0h ; out of memory?
- je int31fail8013 ; if yes, error 8013h
-
- cmp bl,0a1h ; handles exhausted?
- je int31fail8016 ; if yes, error 8016h
-
- cmp bl,0a2h ; invalid handle?
- je int31fail8023 ; if yes, error 8023h
-
- jmp int31fail8010 ; else, error 8010h
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310500x: ; XMS get free memory information
- mov ah,8 ; get largest free memory block in K
- call int310500xcallxms
-
- movzx eax,ax ; EAX = free memory in bytes
- shl eax,10
-
- sub eax,15 ; adjust by extra alignment size
- jnc int310500xsetbuf ; if no overflow, put info to buffer
-
- xor eax,eax ; overflow, so no memory available
- jmp int310500xsetbuf ; put memory information in buffer
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310501x: ; XMS allocate memory block
- call int310500xbxcxtodx ; convert BX:CX bytes to DX K
- mov cx,dx ; preserve size of block in K
-
- mov ah,9 ; allocate DX K of XMS memory
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if yes, convert XMS error to DPMI
-
- mov si,dx ; get DPMI handle from XMS handle
-
- int310501xgotmem:
- mov ah,0ch ; lock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jnz short @@int310501xf0 ; if no, go on
-
- push bx ; yup, preserve error number
-
- mov ah,0ah ; free block causing lock error
- call int310500xcallxms
-
- pop bx ; restore error number
- jmp int310500xerror ; XMS error, return with DPMI error
-
- @@int310501xf0:
- mov di,cx ; low word of DPMI handle is size in K
-
- mov cx,bx ; XMS linear address to DPMI regs
- mov bx,dx
-
- add cx,0fh ; align linear address on paragraph
- adc bx,0
- and cl,0f0h
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310502x: ; XMS free memory block
- mov dx,si ; get XMS handle from DPMI handle
-
- mov ah,0dh ; unlock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- mov ah,0ah ; free memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if yes, convert XMS error to DPMI
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310503x: ; XMS resize memory block
- call int310500xbxcxtodx ; convert BX:CX bytes to DX K
- mov cx,dx ; preserve size of block in K
- mov dx,si ; get XMS handle from DPMI handle
-
- mov ah,0dh ; unlock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- mov bx,cx ; BX = new size in K
- mov ah,0fh ; resize memory block
- call int310500xcallxms
- mov dx,si ; get XMS handle again
- or ax,ax ; error in resize?
- jnz int310501xgotmem ; if no, go to memory block code
-
- push bx ; yup, preserve error number
-
- mov ah,0ch ; lock memory block
- call int310500xcallxms
-
- pop bx ; restore error number
- jmp int310500xerror ; XMS error, return with DPMI error
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31050ax: ; XMS get memory block size and base
- mov dx,si ; get XMS handle from DPMI handle
- mov si,di ; SI = size of block in K
-
- mov ah,0dh ; unlock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- mov ah,0ch ; lock memory block
- call int310500xcallxms
- or ax,ax ; error?
- jz int310500xerror ; if XMS error, return with DPMI error
-
- xor di,di ; convert size in K to size in bytes
- shrd di,si,6
- shr si,6
-
- mov cx,bx ; XMS linear address to DPMI regs
- mov bx,dx
-
- mov ax,cx ; figure out alignment stub
- dec ax
- and ax,0fh
- xor al,0fh
-
- sub di,ax ; subtract alignment stub from size
- sbb si,0
-
- add cx,0fh ; align linear address on paragraph
- adc bx,0
- and cl,0f0h
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
- ; RAW EXTENDED MEMORY FUNCTIONS
- ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
-
- ;-----------------------------------------------------------------------------
- int310500rnomem: ; no free extended memory present
- xor eax,eax ; 0 available extended memory
- jmp int310500xsetbuf ; put memory information in buffer
-
- ;-----------------------------------------------------------------------------
- int310500rbxcxtoebx: ; convert BX:CX bytes to EBX bytes
- pop bp ; pop return address
-
- shl ebx,16 ; EBX = BX:CX
- mov bx,cx
-
- or ebx,ebx ; check for invalid value
- jz int31fail8021 ; if invalid value, error 8021h
-
- add ebx,0fh ; align EBX on paragraph
- and bl,0f0h
-
- jmp bp ; return ok
-
- ;-----------------------------------------------------------------------------
- int310500rfindmcb: ; find MCB for handle SI:DI
- pop bp ; pop return address
-
- shl esi,16 ; ESI = handle SI:DI = address of MCB
- mov si,di
-
- mov edi,cs:rawextmemtop ; EDI -> first memory control block
-
- @@int310500rfindmcbl0:
- cmp edi,esi ; found MCB?
- jne short @@int310500rfindmcbl0f0 ; if no, keep looking
-
- cmp byte ptr [edi-4],0 ; memory block free?
- je int31fail8023 ; if yes, error 8023h
-
- jmp bp ; return ok, found MCB
-
- @@int310500rfindmcbl0f0:
- mov edi,[edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310500rfindmcbl0 ; if yes, loop
-
- jmp int31fail8023 ; fail, error 8023h
-
- ;-----------------------------------------------------------------------------
- int310500radjustused: ; adjust INT 15h extended memory used
- mov eax,cs:rawextmemtop ; EAX -> first memory control block
-
- @@int310500radjustusedl0:
- cmp dword ptr [eax-12],0 ; last memory control block?
- jz short @@int310500radjustusedf0 ; if yes, go to set new used K
-
- mov eax,[eax-12] ; EAX -> next memory control block
- jmp @@int310500radjustusedl0 ; loop
-
- @@int310500radjustusedf0:
- cmp byte ptr [eax-4],0 ; memory block free?
- je short @@int310500radjustusedf1 ; if no, go on
-
- sub eax,[eax-16] ; used, adjust by size of block
-
- @@int310500radjustusedf1:
- sub eax,10h ; adjust by size of MCB
- and eax,0fffffc00h ; align on K
- sub eax,cs:rawextmemtop ; size of extended memory used
- neg eax
- shr eax,10 ; convert from bytes to K
-
- mov ebp,cs:codebase ; EBP = offset of PMODE_TEXT from 0
- mov ds:rawextmemused[ebp],ax ; adjust INT 15h extended memory used
-
- @@int310500radjustuseddone:
- ret ; return
-
- ;-----------------------------------------------------------------------------
- int310500rlinkmcb: ; link memory blocks at ESI and EDI
- mov eax,[esi-16] ; combine two block sizes
- add eax,10h
- add [edi-16],eax ; add size of next block to this one
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- jecxz short @@int310500rlinkmcbf0 ; if no next MCB, done
-
- mov [ecx-8],edi ; set prev MCB in next MCB to this MCB
-
- @@int310500rlinkmcbf0:
- ret ; return
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310500r: ; raw get free memory information
- mov edi,cs:rawextmemtop ; EDI -> first memory control block
-
- xor eax,eax ; running highest free memory block
- @@int310500rl0:
- cmp byte ptr [edi-4],0 ; is block free?
- jne short @@int310500rl0f0 ; if no, loop
-
- mov ebx,[edi-16] ; EBX = size of block
- cmp eax,ebx ; last free block larger?
- ja short @@int310500rl0f0 ; if yes, loop
-
- mov eax,ebx ; found larger block, new largest
-
- @@int310500rl0f0:
- mov edi,[edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310500rl0 ; if yes, loop
-
- jmp int310500xsetbuf ; put memory information in buffer
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310501r: ; raw allocate memory block
- call int310500rbxcxtoebx ; convert BX:CX bytes to EBX bytes
-
- mov edi,cs:rawextmemtop ; EDI -> first memory control block
-
- @@int310501rl0:
- cmp byte ptr ds:[edi-4],0 ; is block free?
- je short @@int310501rl0f2 ; if yes, check block
-
- @@int310501rl0f0:
- mov edi,[edi-12] ; EDI -> next memory control block
- or edi,edi ; is there another MCB?
- jnz @@int310501rl0 ; if yes, loop
-
- jmp int31fail8013 ; fail, error 8013h
-
- @@int310501rl0f2:
- lea ecx,[edi-10h] ; ECX -> possible new MCB
- sub ecx,ebx
-
- mov eax,[edi-16] ; EAX = size of block
- sub eax,ebx ; enough free memory in block?
- jc short @@int310501rl0f0 ; if no, loop
-
- jz short @@int310501rl0f1 ; if exactly same size, continue
-
- sub eax,10h ; adjust for size of new created MCB
- mov [ecx-16],eax ; put size of new block in new MCB
- mov eax,ecx ; set next MCB in old MCB as new one
- xchg [edi-12],eax ; copy next MCB from old to new MCB
- mov [ecx-12],eax
- or eax,eax ; is there a next MCB?
- jz short @@int310501rl0f3 ; if no, go on
-
- mov [eax-8],ecx ; set prev MCB in next MCB to new MCB
-
- @@int310501rl0f3:
- mov [ecx-8],edi ; set prev MCB in new MCB as old one
- mov byte ptr [ecx-4],0 ; set new MCB as free
- mov [edi-16],ebx ; set size of allocated block
-
- @@int310501rl0f1:
- mov byte ptr [edi-4],1 ; set block as allocated
-
- int310501raddxnhandle:
- shld ebx,ecx,16 ; BX:CX = ECX, address of block
- shld esi,edi,16 ; SI:DI = EDI, handle (address of MCB)
-
- call int310500radjustused ; adjust INT 15h extended memory used
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310502r: ; raw free memory block
- call int310500rfindmcb ; find MCB for handle SI:DI
-
- mov byte ptr [edi-4],0 ; set this memory block as free
-
- mov esi,[edi-12] ; ESI -> next memory control block
- or esi,esi ; is there next MCB?
- jz short @@int310502rf0 ; if no, go on
-
- cmp byte ptr [esi-4],0 ; is next memory block free?
- jne short @@int310502rf0 ; if no, go on
-
- call int310500rlinkmcb ; link two memory blocks
-
- @@int310502rf0:
- mov esi,[edi-8] ; ESI -> previous memory control block
- or esi,esi ; is there previous MCB?
- jz short @@int310502rf1 ; if no, go on
-
- cmp byte ptr [esi-4],0 ; is previous memory block free?
- jne short @@int310502rf1 ; if no, go on
-
- xchg esi,edi ; change mcb order for function
- call int310500rlinkmcb ; link two memory blocks
-
- @@int310502rf1:
- call int310500radjustused ; adjust INT 15h extended memory used
-
- jmp int31ok ; return ok
-
- ;─────────────────────────────────────────────────────────────────────────────
- int310503r: ; raw resize memory block
- call int310500rbxcxtoebx ; convert BX:CX bytes to EBX bytes
- mov edx,ebx ; EDX = size of new block
-
- call int310500rfindmcb ; find MCB for handle SI:DI
-
- push ds ; ES = DS for possible block copy
- pop es
-
- sub ebx,[esi-16] ; EBX = change in block size
- jz @@int310503rf0 ; if no change, done
-
- jc @@int310503rf1 ; if block made smaller, just free top
-
- xor eax,eax ; running memory counter
-
- mov ecx,[esi-12] ; ECX -> next MCB
- jecxz short @@int310503rf4 ; if no next MCB, check previous MCB
-
- cmp byte ptr [ecx-4],0 ; next MCB free?
- jne short @@int310503rf4 ; if not, check previous MCB
-
- mov eax,[ecx-16] ; EAX = amount of free memory in block
- add eax,10h ; including memory control block
-
- @@int310503rf4:
- mov ecx,[esi-8] ; ECX -> previous MCB
- jecxz short @@int310503rf5 ; if no previous MCB, check memory
-
- cmp byte ptr [ecx-4],0 ; previous MCB free?
- jne short @@int310503rf5 ; if not, check memory
-
- add eax,[ecx-16] ; add amount of free memory in block
- add eax,10h ; including memory control block
-
- @@int310503rf5:
- cmp eax,ebx ; enough to resize within area
- jb @@int310503rf3 ; if no, try to allocate
-
- or ecx,ecx ; is there a previous MCB?
- jz @@int310503rf6 ; if no, resize to next
-
- cmp byte ptr [ecx-4],0 ; previous MCB free?
- jne short @@int310503rf6 ; if not, resize to next
-
- mov ebp,[ecx-16] ; EBP = size of previous block, try to
- add ebp,10h ; resize within previous block
-
- sub ebp,ebx ; EBP = prev block size - needed size
- jbe short @@int310503rf7 ; if prev block too small, go on
-
- mov edi,ecx ; EDI -> new MCB for new memory block
- sub edi,ebp ; resize will fit entirely
-
- lea eax,[ebp-10h] ; EAX = new size of free block
- mov [ecx-16],eax ; store mew free size in prev MCB
- mov [edi-16],edx ; store new size in new MCB
- mov [ecx-12],edi ; set next MCB in prev MCB to new MCB
- mov [edi-8],ecx ; set prev MCB in new MCB to prev MCB
- mov byte ptr [edi-4],1 ; set new MCB as used
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- or ecx,ecx ; is there a next MCB
- jz @@int310503rf0 ; if no, go to block readjust
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- jmp @@int310503rf0 ; go to block readjust
-
- @@int310503rf7:
- mov edi,ecx ; EDI -> new MCB for new memory block
-
- lea eax,[edx+ebp] ; EAX = size of new block
- mov [edi-16],eax ; store mew free size in new MCB
- mov byte ptr [edi-4],1 ; set new MCB as used
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- jecxz short @@int310503rf8 ; if no next MCB, go on
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- @@int310503rf8:
- add ebp,ebx ; EBP = size of block just acquired
- sub ebx,ebp ; EBX = new size still needed
- jz @@int310503rf0 ; if no more space needed, done
-
- mov esi,edi ; ESI -> new MCB
-
- @@int310503rf6:
- mov edi,[esi-12] ; EDI -> next MCB
-
- mov ecx,[edi-12] ; copy next MCB field
- mov [esi-12],ecx
- jecxz short @@int310503rf9 ; if no next MCB, go on
-
- mov [ecx-8],esi ; set prev MCB in next MCB to this MCB
-
- @@int310503rf9:
- mov eax,[edi-16] ; EAX = size of next memory block
- add eax,10h
-
- sub edi,eax ; EDI -> start of next memory block
- sub eax,ebx ; EAX = amount of free space left
-
- mov ecx,[esi-16] ; ECX = old size of this memory block
- mov [esi-16],edx ; store new size in this MCB
- mov byte ptr [esi-4],1 ; set this MCB as used
-
- sub esi,ecx ; ESI -> start of this memory block
- sub esi,10h
-
- shr ecx,2 ; copy this memory block down in mem
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
-
- add esi,10h ; adjust ESI to top MCB
- mov edi,esi ; EDI -> top MCB
-
- mov ebx,eax ; EBX = negative of space free at top
- neg ebx
- jz @@int310503rf0 ; in no space free, go to done
-
- jmp short @@int310503rf1 ; set new MCBs for moved block
-
- @@int310503rf3:
- mov ebp,edi ; preserve old block MCB address
- sub edx,ebx ; EDX = size of old block
-
- mov bx,[esp+16] ; BX:CX = new block size from stack
- mov cx,[esp+24]
- mov ax,501h ; try to allocate new block
- int 31h
- jc int31failax ; if could not, fail with error AX
-
- shrd eax,esi,16 ; EAX -> new block MCB
- mov ax,di
-
- shrd edi,ebx,16 ; EDI -> start of new block
- mov di,cx
-
- lea esi,[ebp-10h] ; ESI -> start of old block
- sub esi,edx
-
- mov ecx,edx ; copy memory from old block to new
- shr ecx,2
- rep movs dword ptr es:[edi],dword ptr ds:[esi]
-
- mov edx,eax ; EDX -> new block MCB
-
- shld esi,ebp,16 ; SI:DI = handle of old block
- mov di,bp
- mov ax,0502h ; free old block
- int 31h
-
- mov edi,edx ; EDI -> new block MCB for done
-
- jmp short @@int310503rf0 ; go to done
-
- @@int310503rf1:
- lea edi,[esi+ebx] ; EDI -> new MCB for new memory block
-
- lea eax,[ebx+10h] ; EAX = size of freed block
- neg eax
- mov [esi-16],eax ; store freed size in old MCB
- mov [edi-16],edx ; store new size in new MCB
-
- mov ecx,[esi-12] ; copy next MCB field
- mov [edi-12],ecx
- jecxz short @@int310503rf2 ; if no next MCB, go on
-
- mov [ecx-8],edi ; set prev MCB in next MCB to new MCB
-
- @@int310503rf2:
- mov [esi-12],edi ; set next MCB in old MCB as new MCB
- mov [edi-8],esi ; set prev MCB in new MCB as old MCB
- mov byte ptr [edi-4],1 ; set new MCB as used
- mov byte ptr [esi-4],0 ; set old MCB as free
-
- mov ecx,[esi-8] ; ECX -> prev MCB of old MCB
- jecxz short @@int310503rf0 ; if no prev MCB, done
-
- cmp byte ptr [ecx-4],0 ; is previous MCB free?
- jne short @@int310503rf0 ; if no, dont link
-
- push edi ; preserve new MCB
- mov edi,ecx ; top MCB = prev MCB for link function
- call int310500rlinkmcb ; link two memory blocks
- pop edi ; restore new MCB
-
- @@int310503rf0:
- mov ecx,[edi-16] ; ECX = base address of new block
- neg ecx
- lea ecx,[ecx+edi-10h]
-
- jmp int310501raddxnhandle ; return address and handle
-
- ;─────────────────────────────────────────────────────────────────────────────
- int31050ar: ; raw get memory block size and base
- call int310500rfindmcb ; find MCB for handle SI:DI
-
- mov edi,[esi-16] ; EDI = size of memory block
- lea ecx,[esi-10h] ; get base address of memory block
- sub ecx,edi
-
- shld ebx,ecx,16 ; BX:CX = ECX, address of block
- shld esi,edi,16 ; SI:DI = EDI, size of memory block
-
- jmp int31oksinoax ; return ok, with SI, DI, BX, CX
-
- PMODE_TEXT ends
- end
-
-