home *** CD-ROM | disk | FTP | other *** search
- .MODEL LARGE,PASCAL
- .386P
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;TASM Modifications
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;TASM users should set TASMMODE below to TRUE.
-
- TRUE EQU 1
- FALSE EQU 0
-
- TASMMODE = FALSE
-
- IF TASMMODE
- MASM51
- QUIRKS
- NOJUMPS
-
- PUSHW MACRO IMMEDIATE16:REST ;PUSH imm16 (for TASM compatibility)
- IF (@WordSize EQ 4)
- DB 66H
- ENDIF
- DB 68H
- DW IMMEDIATE16
- ENDM
-
- PUSHD MACRO IMMEDIATE32:REST ;PUSH imm32 (for TASM compatibility)
- IF (@WordSize EQ 2)
- DB 66H
- ENDIF
- DB 68H
- DD IMMEDIATE32
- ENDM
-
- INCLUDE XLIBB.INC
- ELSE
- ARG TEXTEQU <>
- OPTION PROC:PRIVATE
- OPTION NOLJMP
- INCLUDE XLIB.INC
- ENDIF
-
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;DSEG declaration. The DSEG data segment has combine type 'FAR_DATA' when
- ;being used in a Borland library. Under most memory models, Borland places all
- ;segments with combine type 'DATA' in DGROUP. Unfortunately, the offsets seen
- ;by the library in such segments may have a different base than those seen by C.
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- IF TASMMODE
- DSEG SEGMENT PARA PUBLIC USE16 'FAR_DATA'
- ELSE
- DSEG SEGMENT PARA PUBLIC USE16 'DATA'
- ENDIF
- ASSUME DS:DSEG
-
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Stacks used for MOVMEM routine. Stacks are dynamically allocated to cover the
- ;possibility that MOVMEM is called both within the main thread of execution and
- ;in interrupt handlers. The possibility of nested interrupts is also covered.
- ;Calls to MOVMEM may be nested four deep. Each dynamically allocated stack
- ;contains 100H bytes.
- ;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ALIGN 8
- DB 800H DUP(0) ;Sufficient space for four stacks
- ISTKPTR DD OFFSET $ ;Initial stack pointer (dynamically adjusted)
- STKALLOC EQU 200H ;Number of bytes allocated per stack for MOVMEM
-
- DSEG ENDS
-
- CSEG SEGMENT PARA PUBLIC USE16 'CODE'
- ASSUME CS:CSEG
-
- IF TASMMODE
- SMALLSTACK
- ENDIF
-
- ;Allocate extended memory block. Error code returned in DX:AX. Arguments are:
- ;NOBYTES:DWORD = Number of bytes to allocate
- ;ADRPTR:DWORD = Far pointer to linear address of allocated block
- ;SIZEPTR:DWORD = Far pointer to size of allocated block
- ;HANDLEPTR:DWORD = Far pointer to handle of allocated block
- XMALLOC PROC FAR,
- ARG NOBYTES:DWORD,ADRPTR:DWORD,SIZEPTR:DWORD,HANDLEPTR:DWORD ;Number of bytes to allocate
- PUSH EBX
- PUSH ECX
- PUSH DS
- MOV EAX,NOBYTES
- CALL GETMEM
- OR EAX,EAX
- JNZ SHORT EXIT
- PUSH EBX
- LDS BX,ADRPTR
- MOV [BX],EDX
- LDS BX,SIZEPTR
- MOV [BX],ECX
- LDS BX,HANDLEPTR
- POP DWORD PTR [BX]
- EXIT: PUSH EAX ;Return error code in DX:AX
- POP AX
- POP DX
- POP DS
- POP ECX
- POP EBX
- RET
- XMALLOC ENDP
-
- ;Release extended memory block. Error code returned in DX:AX. Arguments are:
- ;HANDLE:DWORD = Handle to previously allocated block
- XFREE PROC FAR,
- ARG HANDLE:DWORD ;Handle to previously allocated block
- MOV EAX,HANDLE
- CALL FREEMEM
- PUSH EAX ;Put error code in DX:AX
- POP AX
- POP DX
- RET
- XFREE ENDP
-
- ;Map physical memory to logical address space. Error code returned in DX:AX.
- ;Arguments are:
- ;PHYSADR:DWORD = Linear address of physical memory
- ;BLKSIZE:DWORD = Size of memory block (in bytes)
- ;LOGADRPTR:DWORD = Far pointer to DWORD to receive logical address
- MAPIOMEM PROC FAR,
- ARG PHYSADR:DWORD,BLKSIZE:DWORD,LOGADRPTR:DWORD
- PUSH BX
- PUSH DS
- MOV EDX,PHYSADR
- MOV EAX,BLKSIZE
- PUSHD OFFSET PMMAPIO
- CALL CALLPM
- LDS BX,LOGADRPTR
- MOV [BX],EDX
- PUSH EAX ;Place error code in DX:AX
- POP AX
- POP DX
- POP DS
- POP BX
- RET
- MAPIOMEM ENDP
-
- ;Move memory. This routine is suitable for interrupt handlers. It uses a
- ;stack in DSEG rather than TSEG. Arguments are:
- ;DESTADR:DWORD = Destination address.
- ;SOURCEADR:DWORD = Source address.
- ;NOBYTES:DWORD = Number of bytes to transfer.
- ALIGN 16
- MOVMEM PROC FAR,
- ARG DESTADR:DWORD,SOURCEADR:DWORD,NOBYTES:DWORD
- PUSHAD
- PUSH DS
- PUSH ES
- PUSH FS
- PUSH GS
- MOV AX,DSEG
- MOV DS,AX
- MOV ESI,SOURCEADR ;Load registers as required by MOVMEM32
- MOV EDI,DESTADR
- MOV ECX,NOBYTES
- MOV EDX,ISTKPTR ;Get currently available pointer for the dynamic stack
- SUB ISTKPTR,STKALLOC ;Prepare dynamic stack for possibility of interrupt call back to this routine
- MOV BX,SP ;Save the old stack in EBX
- PUSH SS
- PUSH BX
- POP EBX
- MOV SS,AX ;Load the dynamic stack
- MOV ESP,EDX
- CALL SWITCHPM ;Switch to 16-bit protected mode
- PUSHW 0H ;PUSH 32-bit far return address back to this procedure
- MOV AX,CSEGSEL
- PUSH AX
- PUSHD OFFSET RETADR
- PUSHW 0H ;PUSH 32-bit far address of MOVMEM32
- MOV AX,TSEGSEL
- PUSH AX
- PUSHD OFFSET MOVMEM32
- MOV DS,FLATDSEL ;Switch to flat data model
- DB 66H ;Execute 32-bit RETF
- RETF
- RETADR: CALL SWITCHRM ;Switch back to real mode
- PUSH EBX ;Load calling stack
- LSS SP,[ESP]
- ADD ISTKPTR,STKALLOC ;Adjust dynamic stack pointer
- POP GS
- POP FS
- POP ES
- POP DS
- POPAD
- RET
- MOVMEM ENDP
-
- ;Calculate linear address from segment address. Call with segment address on
- ;stack. Linear address returned in DX:AX.
- LINADR PROC FAR,
- ARG SEGADDRESS:DWORD ;Segment address of variable
- MOV AX,WORD PTR SEGADDRESS[2] ;Do not corrupt high words (might be used in 16-bit interrupt handler)
- XOR DX,DX
- SHLD DX,AX,4
- SHL AX,4
- ADD AX,WORD PTR SEGADDRESS[0]
- ADC DX,0
- RET
- LINADR ENDP
-
- ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- ;Interfaces to XLIB file management routines. Each of these procedures should
- ;be called with the segment address of the control block on the stack. These
- ;routines cannot be called during interrupts since each routine calls DOS.
- ;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- ;Create file.
- XFCREATE PROC FAR
- PUSHD OFFSET PMXCREATE
- JMP CHAINTOPM
- XFCREATE ENDP
-
- ;Open file.
- XFOPEN PROC FAR
- PUSHD OFFSET PMXOPEN
- JMP CHAINTOPM
- XFOPEN ENDP
-
- ;Close file.
- XFCLOSE PROC FAR
- PUSHD OFFSET PMXCLOSE
- JMP CHAINTOPM
- XFCLOSE ENDP
-
- ;Load file
- XFLOAD PROC FAR
- PUSHD OFFSET PMXLOAD
- JMP CHAINTOPM
- XFLOAD ENDP
-
- ;Save file.
- XFSAVE PROC FAR
- PUSHD OFFSET PMXSAVE
- JMP CHAINTOPM
- XFSAVE ENDP
-
- ;Random read file.
- XFREAD PROC FAR
- PUSHD OFFSET PMXREAD
- JMP CHAINTOPM
- XFREAD ENDP
-
- ;Random write file.
- XFWRITE PROC FAR
- PUSHD OFFSET PMXWRITE
- JMP CHAINTOPM
- XFWRITE ENDP
-
- ;Transfer control to protected mode after converting segment address of control
- ;block to linear address in EAX.
- CHAINTOPM PROC FAR
- PUSH DWORD PTR [ESP+8] ;PUSH segment address of control block
- CALL LINADR
- PUSH DX
- PUSH AX
- POP EAX
- CALL CALLPM
- RET 4
- CHAINTOPM ENDP
-
- PUBLIC PASCAL XMALLOC
- PUBLIC PASCAL XFREE
- PUBLIC PASCAL MAPIOMEM
- PUBLIC PASCAL LINADR
- PUBLIC PASCAL MOVMEM
- PUBLIC PASCAL XFCREATE
- PUBLIC PASCAL XFOPEN
- PUBLIC PASCAL XFCLOSE
- PUBLIC PASCAL XFLOAD
- PUBLIC PASCAL XFSAVE
- PUBLIC PASCAL XFREAD
- PUBLIC PASCAL XFWRITE
-
- CSEG ENDS
-
- TSEG SEGMENT PARA PUBLIC USE32 'CODE'
- ASSUME CS:TSEG
-
- IF TASMMODE
- LARGESTACK
- ENDIF
-
- ;Transfer memory. Call with source address in ESI, destination address in EDI,
- ;and number of bytes to transfer in ECX. Does not preserve registers. This
- ;routine is far and is therefore a departure from XLIB policy. This approach
- ;is used because the routine is not entered with the standard XLIB mode switch
- ;procedures, CALLPM and ENTERPM. Standard mode switch procedures are not used
- ;because they are not reentrant and therefore cannot be used in interrupt
- ;handlers.
- ALIGN 16
- MOVMEM32 PROC FAR
- CMP EDI,ESI
- JBE ENTERDN4
- JMP ENTERUP4
- ALIGN 4
- UP4LOOP: MOV EAX,[ESI+1*ECX] ;Destination address is higher than source address
- MOV [EDI+1*ECX],EAX
- ENTERUP4: SUB ECX,4
- JAE UP4LOOP
- ADD ECX,4
- JNZ ENTERUP1
- RET
- ALIGN 4
- UP1LOOP: MOV AL,[ESI+1*ECX]
- MOV [EDI+1*ECX],AL
- ENTERUP1: DEC ECX
- JNS UP1LOOP
- RET
- ALIGN 4
- DN4LOOP: MOV EAX,[ESI] ;Destination address is lower than source address
- MOV [EDI],EAX
- ADD ESI,4
- ADD EDI,4
- ENTERDN4: SUB ECX,4
- JAE DN4LOOP
- ADD ECX,4
- JNZ ENTERDN1
- RET
- ALIGN 4
- DN1LOOP: MOV AL,[ESI]
- MOV [EDI],AL
- INC ESI
- INC EDI
- ENTERDN1: DEC ECX
- JNS DN1LOOP
- RET
- MOVMEM32 ENDP
-
- TSEG ENDS
- END
-