home *** CD-ROM | disk | FTP | other *** search
- TITLE MEMCXB ;C version
- PAGE 55,132
- ;multiple routines
- ;xb$malloc
- ;xb$free
- ;xb$SetHandleCount (no longer available with this replacement module)
- ;-----------------------------------------------------------------------|
- ; ScanSoft (C)1992 Cornel H Huth ALL RIGHTS RESERVED |
- ;-----------------------------------------------------------------------|
- ; date: 31-Aug-93 |
- ; function: Memory routines for C compilers |
- ; that do not allow DOS allocations to be mixed with |
- ; _malloc allocations (including _calloc, etc.) |
- ; notes: This malady afflicts Borland C compilers |
- ; All registers saved since there's no telling what |
- ; registers the runtime code uses (ax,bp not saved) |
- ; |
- ; |
- ;The code below will work in either LARGE or HUGE memory modules. |
- ;It will not, as written, work in the medium model. With minor changes, |
- ;the medium model could be supported (though this patch isn't needed |
- ;for Borland medium memory models. Not tested in LARGE. |
- ; |
- ;This code was written with MASM 5.10A in mind though TASM should |
- ;handle it, too. |
- ; |
- ;To assemble: |
- ; |
- ; C>masm memcxb /mx; (/mx=preserve case on globals) |
- ; |
- ;See FIX104.TXT for more info. |
- ;-----------------------------------------------------------------------|
- WPTR EQU <WORD PTR>
-
- .MODEL LARGE,PASCAL
-
- .DATA
-
- PUBLIC _maxPackRAM
- PUBLIC _maxIndexToken
-
- ;The following max values are for compiler/run-time code that gets flakey
- ;on large allocations made using the patch module. These values can be
- ;bumped to there max (65504 and 2, respectively) if your particular RT
- ;can handle it. In the default MEMXB.OBJ (this is MEMCXB.OBJ) the max
- ;values are used (since no RT is involved to flake out).
-
- _maxPackRAM dw 32768 ;max bytes PackRecords can allocate (8K-63K)
- _maxIndexToken dw 0 ;max bytes Reindex can allocate
- ;where token 0=32K, 1=64K, and 2+=128K)
-
- .CODE
-
- EXTRN _malloc:FAR
- EXTRN _free:FAR
-
- ;The Tracker lists are allocated in code segment to minimize
- ;impact on DGROUP
-
- ;MAXTRACKER is the number of allocations that can be open at
- ;any one time. Consider each open file to require one Track.
- ;A good MAXTRACKER value would be the total number of files you
- ;require to be open at one time plus 5. Each MAXTRACKER
- ;requires 6 bytes of code space. Unless you're starving for
- ;RAM, MAXTRACKER is fine at 254 (uses about 1.5K of code space.)
-
- MAXTRACKER EQU 254
-
- ;TrackerFP stores far pointers as returned by _malloc
- ;so that _free can be used (_free requires exact FP match)
- EVEN
- TrackerFP dd MAXTRACKER DUP (0) ;32-bit pointer as returned by _malloc
- dd 0 ;and required by _free
-
- ;TrackerSeg stores the 16-bit segment pointer converted from
- ;the far pointer returned by _malloc. See xb$malloc for how
- ;this is done. This is used as a lookup value in xb$free.
-
- TrackerSeg dw MAXTRACKER DUP (0) ;thunk it to a 16-bit segment pointer
- dw -1
-
- ;-----------------------------------------------------------------------|
- ; date: 30-Sep-92 |
- ; function: allocate memory |
- ; caller: FAR, ASSEMBLY |
- ; stack: n/a |
- ; in: bx=paragraphs to allocate |
- ; out: NC=ax=seg |
- ; CY=ax=8=not enough memory |
- ; uses: ax (return) |
- ; notes: call with bx=FFFF and bx returns w/ largest block free |
- ; (according to DOS) |
- ;-----------------------------------------------------------------------|
-
- xb$malloc PROC USES cx dx si di es ds
-
- cmp bx,-1 ;just asking for available memory?
- jne xb$malloc01 ;no
- mov ah,48h ;yes
- int 21h
- jmp SHORT xb$mallocXit
-
- xb$malloc01: mov cx,MAXTRACKER ;scan for next free descriptor
- sub ax,ax ;0 indicates available
- push cs
- mov di,OFFSET TrackerSeg
- pop es ;es:di->TrackSeg start
- repne scasw
- jne xb$mallocEx ;none available
- mov ax,di
- sub ax,OFFSET TrackerSeg+2 ;ax=available slot (word)
-
- push bx ;save size for return
- push ax ;save slot
-
- mov ax,1
- push ax ;size of
- sub ax,ax
- push ax ;high-word of request
- mov ax,bx ;paras requested
- inc ax ;bump para request so we can norm it
- shl ax,1 ;(thunk it would be more like it)
- shl ax,1
- shl ax,1
- shl ax,1 ;paras to bytes
- push ax ;low-word of request
-
- mov ax,DGROUP ;definite requirement for C7
- mov ds,ax ;(though this patch not needed for C7!)
-
- call _malloc ;appease the Borland Gods
- add sp,6 ;here dx:ax is far pointer to block
-
- pop di ;get back slot
-
- mov bx,dx ;check for null pointer return
- or bx,ax ;allocation okay?
- pop bx ;get back size
- jz xb$mallocEx ;no
-
- mov si,di ;word slot index for TrackerSeg
- shl di,1 ;dword slot index for TrackerFP
- mov WPTR cs:[TrackerFP+di],ax
- mov WPTR cs:[TrackerFP+di+2],dx
-
- ;normalize the 32-bit pointer to a 16-bit segment pointer
- ;we can do this because we requested 1 additional paragraph
- ;so that we can just drop the normalized offset and start
- ;using the allocated memory block at the next paragraph
-
- ;;since we won't be using the fractional-para offset of the
- ;;norm'ed far pointer we can skip the overhead
-
- ;;mov bx,ax ;save full offset
- ;;and ax,000Fh ;non-paragraph portion
- ;;mov cx,ax ;ax is normalized offset
- ;;mov ax,bx ;get full offset back
-
- shr ax,1 ;convert offset to full paras
- shr ax,1
- shr ax,1
- shr ax,1
- add ax,dx ;add segment in
- inc ax ;bump to next paragraph
- mov cs:[TrackerSeg+si],ax
- clc ;return 16-bit segment pointer in ax
- xb$mallocXit: ret ;that BULLET will use
-
- xb$mallocEx: mov ax,8
- stc
- jmp SHORT xb$mallocXit
-
- xb$malloc ENDP
-
- ;-----------------------------------------------------------------------|
- ; date: 30-Sep-92 |
- ; function: free allocated memory |
- ; caller: FAR, ASSEMBLY |
- ; stack: n/a |
- ; in: es=segment pointer of block to free |
- ; out: NC=okay (at least this code, _free has not return code)|
- ; CY=ax=9 invalid block (segment not in descriptor list |
- ; uses: ax (return) |
- ; notes: see xb$malloc above for more info |
- ;-----------------------------------------------------------------------|
-
- xb$free PROC USES bx cx dx si di ds es
-
- mov cx,MAXTRACKER ;scan for matching descriptor
- mov ax,es ;search for this segment pointer
- push cs
- mov di,OFFSET TrackerSeg
- pop es ;es:di->TrackerSeg start
- repne scasw
- jne xb$freeEx ;not found, must be invalid block
-
- sub ax,ax
- sub di,OFFSET TrackerSeg+2 ;di=matched slot (word)
-
- push di ;save slot
-
- shl di,1 ;dword slot index
- push WPTR cs:[TrackerFP+di+2];segment to block to release
- push WPTR cs:[TrackerFP+di] ;offset
-
- mov ax,DGROUP
- mov ds,ax
-
- call _free ;appease them some more
- add sp,4
- sub ax,ax
- mov WPTR cs:[TrackerFP+di+2],ax ;clear descriptor info
- mov WPTR cs:[TrackerFP+di],ax
-
- pop di ;get word slot index
-
- mov cs:[TrackerSeg+di],ax ;make slot available
- xb$freeXit: ret
-
- xb$freeEx: mov ax,9
- stc
- jmp xb$freeXit
- xb$free ENDP
-
- ;-----------------------------------------------------------------------|
- ; date: 30-Sep-92 |
- ; function: set maximum handle count |
- ; caller: FAR, ASSEMBLY |
- ; stack: n/a |
- ; in: bx=handle count |
- ; out: NC=okay |
- ; CY=ax=error number |
- ; uses: ax (return) |
- ; notes: Cannot use DOS INT21/67 since it makes a DOS memory |
- ; allocation call which, as you know, cannot be |
- ; issued when using Borland's _malloc functions. |
- ;-----------------------------------------------------------------------|
-
- xb$SetHandleCount PROC
-
- mov ax,1 ;function not available for Borland C
- stc ;via this route
- ret
-
- xb$SetHandleCount ENDP
-
- END
-
-