|
|
TITLE lib - various C library routines
; Windows Write, Copyright 1985-1992 Microsoft Corporation ;============================================================================= ; This file contains various C library functions (and a few other ; functions) with the PL/M calling conventions. These routines ; may some day make their way into a real library of some kind, but ; until then, you'll just have to link this file in with the rest ; of your code. ;=============================================================================
?PLM = 1 ?WIN = 1
;*** See note about cmacros2.inc in DOSLIB.ASM include cmacros3.inc
; ;createSeg _MMP2, code, byte, public, CODE ;
sBegin CODE ; assumes CS,_MMP2 assumes CS,CODE
;------------------------------------------------------------------------------ ; bltbyte (pbFrom, pbTo, cb) - a block transfer of bytes from pbFrom to ; pbTo. The size of the block is cb bytes. This bltbyte() handles the ; case of overlapping source and destination. bltbyte() returns a pointer ; to the end of the destination buffer (pbTo + cb). NOTE - use this ; bltbyte to transfer within the current DS only--use the bltbx for ; FAR blts. ;-----------------------------------------------------------------------------
cProc bltbyte, <FAR, PUBLIC>, <SI, DI> parmDP <pbFrom, pbTo> parmW <cb> cBegin bltbyte mov si,pbFrom ; get pointers and length of blt mov di,pbTo mov cx,cb mov ax,di ; calculate return value add ax,cx push ds ; set up segment registers pop es cmp si,di ; reverse direction of the blt if jae bltb1 ; necessary add si,cx add di,cx dec si dec di std bltb1: rep movsb cld cEnd bltbyte
;----------------------------------------------------------------------------- ; bltbx (qbFrom, qbTo, cb) - same as bltbyte above except everything is ; handled as FAR pointers. ;-----------------------------------------------------------------------------
cProc bltbx, <FAR, PUBLIC>, <SI, DI, DS> parmD <qbFrom, qbTo> parmW <cb> cBegin bltbx les di,qbTo lds si,qbFrom mov cx,cb mov ax,di add ax,cx cmp si,di jae bltbx1 add si,cx add di,cx dec si dec di std bltbx1: rep movsb cld mov dx,es cEnd bltbx
;------------------------------------------------------------------------------ ; blt (pFrom, pTo, cw) - a block transfer of wFills from pFrom to pTo; ; The size of the block is cw wFills. This blt() handles the case of ; overlapping source and destination. blt() returns a pointer to the ; end of the destination buffer (pTo + cw). NOTE - use this blt() to ; to transfer within the current DS only--use the bltx for FAR blts. ;-----------------------------------------------------------------------------
cProc blt, <FAR, PUBLIC>, <SI, DI> parmDP <pFrom, pTo> parmW <cw> cBegin blt mov si,pFrom ; get pointers and length of blt mov di,pTo mov cx,cw mov ax,di ; calculate return value mov bx,cx shl bx,1 add ax,bx push ds ; set up segment registers pop es cmp si,di ; reverse direction of the blt if jae blt1 ; necessary dec bx dec bx add si,bx add di,bx std blt1: rep movsw cld cEnd blt
;----------------------------------------------------------------------------- ; bltx (qFrom, qTo, cw) - same as blt() above except everything is ; handled as FAR pointers. ;-----------------------------------------------------------------------------
cProc bltx, <FAR, PUBLIC>, <si, di, ds> parmD <qFrom, qTo> parmW <cw> cBegin bltx les di,qTo lds si,qFrom mov cx,cw mov ax,di mov bx,cx shl bx,1 add ax,bx cmp si,di jae bltx1 dec bx dec bx add si,bx add di,bx std bltx1: rep movsw cld mov dx,es cEnd bltx
;----------------------------------------------------------------------------- ; bltc (pTo, wFill, cw) - fills cw words of memory starting at pTo with wFill. ;-----------------------------------------------------------------------------
cProc bltc, <FAR, PUBLIC>, <DI> parmDP <pTo> parmW <wFill, cw> cBegin bltc mov ax,ds ; we are filling in the data segment mov es,ax mov di,pTo ; get the destination, constant, and count mov ax,wFill mov cx,cw cld ; the operation is forward rep stosw ; fill memory cEnd bltc
;----------------------------------------------------------------------------- ; bltcx (qTo, wFill, cw) - fills cw words of memory starting at FAR location ; qTo with wFill. ;-----------------------------------------------------------------------------
cProc bltcx, <FAR, PUBLIC>, <DI> parmD <qTo> parmW <wFill, cw> cBegin bltcx les di,qTo ; get the destination, constant, and count mov ax,wFill mov cx,cw cld ; the operation is forward rep stosw ; fill memory cEnd bltcx
;----------------------------------------------------------------------------- ; bltbc (pTo, bFill, cb) - fills cb bytes of memory starting at pTo with ; bFill. ;-----------------------------------------------------------------------------
cProc bltbc, <FAR, PUBLIC>, <DI> parmDP <pTo> parmB <bFill> parmW <cb> cBegin bltbc mov ax,ds ; we are filling in the data segment mov es,ax mov di,pTo ; get the destination, constant, and count mov al,bFill mov cx,cb cld ; the operation is forward rep stosb ; fill memory cEnd bltbc
;----------------------------------------------------------------------------- ; bltbcx (qTo, bFill, cb) - fills cb bytes of memory starting at FAR location ; qTo with bFill. ;-----------------------------------------------------------------------------
cProc bltbcx, <FAR, PUBLIC>, <DI> parmD <qTo> parmB <bFill> parmW <cb> cBegin bltbcx les di,qTo ; get the destination, constant, and count mov al,bFill mov cx,cb cld ; the operation is forward rep stosb ; fill memory cEnd bltbcx
;----------------------------------------------------------------------------- ; MultDiv(w, Numer, Denom) returns (w * Numer) / Denom rounded to the nearest ; integer. A check is made so that division by zero is not attempted. ;-----------------------------------------------------------------------------
cProc MultDiv, <FAR, PUBLIC> parmW <w, Numer, Denom> cBegin MultDiv mov bx,Denom ; get the demoninator mov cx,bx ; cx holds the final sign or bx,bx ; ensure the denominator is positive jns md1 neg bx md1: mov ax,w ; get the word we are multiplying xor cx,ax ; make cx reflect any sign change or ax,ax ; ensure this word is positive jns md2 neg ax md2: mov dx,Numer ; get the numerator xor cx,dx ; make cx reflect any sign change or dx,dx ; ensure the numerator is positive jns md3 neg dx md3: mul dx ; multiply mov cl,bl ; get half of the demoninator to adjust for rounding sar bx,1 add ax,bx ; adjust for possible rounding error adc dx,0 ; this is really a long addition sal bx,1 ; restore the demoninator or bl,cl cmp dx,bx ; check for overflow jae md5 div bx ; divide or ax,ax ; if sign is set, then overflow occured js md5 or cx,cx ; put the sign on the result jns md4 neg ax md4:
cEnd MultDiv
md5: mov ax,7FFFh ; return the largest integer or cx,cx ; with the correct sign jns md4 neg ax jmp md4
;----------------------------------------------------------------------------- ; FSzSame (szOne, szTwo) - Compare strings, return 1=Same, 0=different ; Both strings in DS ;-----------------------------------------------------------------------------
cProc FSzSame, <FAR, PUBLIC>, <SI> parmDP <szOne> parmDP <szTwo> cBegin FszSame
mov bx,szOne mov si,szTwo
fszloop: mov al,[bx] cmp al,[si] jnz notequal ; found inequality - return FALSE inc bx inc si test al,al jnz fszloop ; didn't reach a zero-terminator compare next char
mov ax,1 jmp fszend notequal: xor ax,ax fszend:
cEnd FszSame
;----------------------------------------------------------------------------- ; CchDiffer (rgch1,rgch2,cch) - compare 2 strings, returning cch of ; shortest prefix leaving a common remainder ; implementation of the following C code ; note rather odd return values: 0 if =, # of unmatched chars +1 otherwise. ; note comparison is from end of string ;** int CchDiffer(rgch1, rgch2, cch) ;** register CHAR *rgch1, *rgch2; ;** int cch; ;** {{ /* Return cch of shortest prefix leaving a common remainder */ ;** int ich;
;** for (ich = cch - 1; ich >= 0; ich--) ;** if (rgch1[ich] != rgch2[ich]) ;** break; ;** return ich + 1; ;** }} ;-----------------------------------------------------------------------------
cProc CchDiffer, <FAR, PUBLIC>, <SI,DI> parmDP <rgch1> parmDP <rgch2> parmW <cch> cBegin CchDiffer mov ax,ds ; set es=ds for string ops mov es,ax
mov si,rgch1 mov di,rgch2 mov cx,cch ; loop count in cx mov ax,cx ; compare from end of string down dec ax add si,ax add di,ax std repz cmpsb ; compare strings jz DiffRet ; return 0 if strings = inc cx ; else increment return value DiffRet: mov ax,cx ; return # of unmatched chars cld ; restore to be nice cEnd CchDiffer
ifdef DEBUG
;----------------------------------------------------------------------------- ; toggleProf () - toggles winprof (windows profiler) profiling on or off. ; this calls to hard coded locations that both symdeb and winprof know ; about - see Lyle Kline for an actual explanation. ;-----------------------------------------------------------------------------
cProc toggleProf, <FAR, PUBLIC> cBegin toggleProf
; ** the following strings are stored by the profiler starting at ; ** 100h of the loaded segment. This routine checks that the 1st ; ** 3 letters of each string are in the proper location to determine ; ** whether the profiler is already loaded.
; **** segname db "SEGDEBUG",0 ; **** db "PROFILER",0
push es push di push si xor ax,ax mov es,ax mov ax,es:[14] ;Get segment down there. mov es,ax mov di,0100h ;See if Profiler in memory.
cmp Byte Ptr es:[di],'S' jnz $0001
cmp Byte Ptr es:[di+1],'E' jnz $0001
cmp Byte Ptr es:[di+2],'G' jnz $0001
cmp Byte Ptr es:[di+9],'P' jnz $0001
cmp Byte Ptr es:[di+10],'R' jnz $0001
mov ax,30 ;Type of call. push ax
mov di,00FCh call Dword Ptr es:[di] ; call to profiler toggle routine. add sp,2 ; winprof uses normal c conventions
$0001: pop si pop di pop es
cEnd toggleProf
endif
;----------------------------------------------------------------------------- ; void OsTime( pTime ) ; ; pTime is a pointer to a structure of the form: ; struct { ; char min; Minutes (0-59) ; char hour; Hours (0-23) ; char hsec; Hundredths of seconds (0-99) ; char sec; Seconds (0-59) ; ; Get current time into structure ; DOS-specific ;-----------------------------------------------------------------------------
cProc OsTime, <FAR, PUBLIC> parmDP <pTime> cBegin OsTime
mov ah,2ch int 21h
mov bx,pTime mov WORD PTR [bx], cx mov WORD PTR [bx+2], dx
cEnd OsTime
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Added by PaulT 3/23/89, borrowed from PC Word 5: ; ; IchIndexLp(lpsz, ch) ; char far *lpsz; ; int ch; ; Searches for ch in lpsz and returns the index (-1 if not found) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; cProc IchIndexLp,<FAR, PUBLIC> parmD lpsz parmB chT cBegin mov dx, di ; Save di les di, lpsz mov ah, chT xor al,al mov bx, di ; Save initial pointer ; **** Can't access parms anymore
mov cx,-1 repnz scasb ; Must have '\0' or ax, ax jz LDoneILI mov al, ah ; al = chT not cx dec cx mov di, bx repnz scasb jz LDoneILI mov di, bx LDoneILI: mov ax, di sub ax, bx dec ax ; ax = return value mov di, dx ; Restore di cEnd IchIndexLp
sEnd CODE
END
|