home *** CD-ROM | disk | FTP | other *** search
- unit ptrmath;
- {*************************************************************
- * A unit of functions for directly manipulating TP pointers. *
- * Requires a version of TP with the built-in assembler. *
- * (C) Daniel A. Bronstein, Michigan State University, 1991. *
- * May be freely used provided attribution is made. *
- *************************************************************}
-
- Interface
-
- function ptrinc(p:pointer;w:word):pointer;
- function ptrdec(p:pointer;w:word):pointer;
- function baseptr(p:pointer):pointer;
-
- Implementation
-
- {************************************
- * PTRINC - Inc a pointer by a word. *
- ************************************}
- function ptrinc(p:pointer;w:word):pointer;assembler;
- asm
- les di,p {Load pointer in ES:DI and}
- mov bx,di {save DI in BX for later use.}
- add di,w {Add w to DI and see if we}
- cmp di,bx {have wrapped around.}
- ja @xit {If not, all ok, so exit, else}
- xor di,di {return a nil pointer by 0'ing}
- mov es,di {DI and ES.}
- @xit:
- mov ax,di {Return the pointer in}
- mov dx,es {DX:AX.}
- end;
-
- {************************************
- * PTRDEC - Dec a pointer by a word. *
- ************************************}
- function ptrdec(p:pointer;w:word):pointer;assembler;
- asm
- les di,p {Same system as PTRINC.}
- mov bx,di
- sub di,w
- cmp di,bx
- jb @xit
- xor di,di
- mov es,di
- @xit:
- mov ax,di
- mov dx,es
- end;
-
- {*******************************************************************
- * BASEPTR - Create a base pointer - Return pointer in the form *
- * $XXXX:$000X; e.g., $66F3:$800A = $6EF3:$000A. This is very *
- * useful as some versions of DOS on some machines may not always *
- * return allocated memory in this format, which allows for easy *
- * wrap-around checks in PTRINC and PTRDEC. Does not work if the *
- * original segment is greater than $F000 as it might itself *
- * wrap-around in that case, but since TP cannot allocate memory in *
- * the $F000 segment that should not be a problem. *
- * Algorithm is: *
- * power = 12 *
- * divr = 2^power *
- * while offset > 16 *
- * quot = offset / divr *
- * offset = offset - (quot * divr) *
- * power = power - 4 *
- * divr = 2^power *
- * segment = segment + (quot * divr) *
- *******************************************************************}
-
- function baseptr(p:pointer):pointer;assembler;
- asm
- les di,p {Load the ptr and}
- mov dx,es {move ES to DX.}
- cmp dx,0F000h {If ES(DX) > $F000, danger of}
- ja @xit {wrap-around, so exit.}
- mov cl,12 {Prepare CL for SHL & SHR.}
- @loop:
- cmp di,10h {If DI < 16 then done,}
- jb @xit {so exit;}
- mov ax,di {Move DI to AX and}
- shr ax,cl {divide by 2^CL (4096,256,16),}
- mov bx,ax {move AX to BX and}
- shl bx,cl {multiply by 2^CL then}
- sub di,bx {subtract from DI.}
- sub cl,4 {Reduce CL by 4,}
- shl ax,cl {multiply AX by 2^CL}
- add dx,ax {and add it to DX,}
- jmp @loop {then loop back.}
- @xit:
- mov ax,di {Return the ptr in DX:AX.}
- end;
-
- end.