home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR41
/
EMSIF24.ZIP
/
TESTUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-15
|
36KB
|
769 lines
/***************************************************************************
* TESTUTIL.C *
* MODULE: TESTUTIL *
* OS: DOS *
* VERSION: 1.0 *
* DATE: 11/15/91 *
* *
* Copyright (c) 1991 James W. Birdsall. All Rights Reserved. *
* *
* Requires testutil.h to compile. *
* Compiles under Borland C++ 2.0, TC 2.0, or MSC 6.00A. *
* *
* This file contains various utility functions used to fill and check *
* blocks of memory and perform other basic services. Many are coded in *
* in-line assembly language to improve speed. The in-line assembly is *
* compatible with both Turbo/Borland C[++] and MSC 6.00A. If your *
* compiler does not support in-line assembly, or your compiler requires *
* an external assembler which you do not have, or you simply do not wish *
* to use the in-line assembly code, the functions also contain C code *
* versions. The C code versions are the default; in order to use the *
* in-line assembly, you must define the symbol INLINE_ASM when *
* compiling. *
* *
***************************************************************************/
/*
** system includes <>
*/
#include <string.h>
#include <dos.h>
/*
** custom includes ""
*/
#include "testutil.h"
/*
** local #defines
*/
/*
** misc: copyright strings, version macros, etc.
*/
/*
** typedefs
*/
/*
** global variables
*/
/*
** static globals
*/
/*
** function prototypes
*/
/*
** functions
*/
/***************************************************************************
* FUNCTION: FARMEMCHECK *
* *
* DESCRIPTION: *
* *
* This function scans a block of memory looking for bytes which do *
* not match checkchar. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory to scan *
* len - length of block *
* checkchar - value which should be matched *
* *
* EXIT: *
* *
* Returns 0 if all bytes match, nonzero if mismatch found. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int farmemcheck(unsigned char far *buffer, unsigned int len,
unsigned char checkchar)
{
int retval = 0;
unsigned char huge *temp;
/* normalize far pointer and turn into huge pointer */
temp = normptr(buffer);
#ifdef INLINE_ASM
ASM push bx /* preserve registers */
ASM push cx
ASM push si
ASM push ds
ASM lds si, [temp] /* load pointer into DS:SI */
ASM mov cx, [len] /* load length into CX */
ASM mov bl, [checkchar] /* load match value into BX */
looptop:
ASM lodsb /* load next byte into AL */
ASM cmp al, bl /* test against BL */
ASM jne nomatch /* if not equal, exit loop */
ASM loop looptop /* otherwise loop */
ASM jmp match
nomatch:
ASM mov WORD PTR [retval], 1 /* return nonzero on mismatch */
match:
ASM pop ds /* restore register values */
ASM pop si
ASM pop cx
ASM pop bx
#else
for (; len; len--, temp++) /* do the same thing in C */
{
if (*temp != checkchar)
{
retval = 1;
break;
}
}
#endif
return retval;
} /* end of farmemcheck() */
/***************************************************************************
* FUNCTION: LFARMEMCHECK *
* *
* DESCRIPTION: *
* *
* This function scans a block of memory longer than 64K looking for *
* bytes which do not match checkchar. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory to scan *
* len - length of block *
* checkchar - value which should be matched *
* *
* EXIT: *
* *
* Returns 0 if all bytes match, nonzero if mismatch found. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int lfarmemcheck(unsigned char far *buffer, unsigned long len,
unsigned char checkchar)
{
int retval;
unsigned int copylen;
unsigned char huge *temp;
/* normalize far pointer and turn into huge pointer */
temp = normptr(buffer);
while (len > 0L)
{
copylen = ((len > 65000L) ? 65000U : (unsigned int) len);
if ((retval = farmemcheck((void far *) temp, copylen, checkchar)) != 0)
{
return retval;
}
temp = normptr((unsigned char far *)(temp + copylen));
len -= copylen;
}
return retval;
} /* end of lfarmemcheck() */
/***************************************************************************
* FUNCTION: LFMEMCMP *
* *
* DESCRIPTION: *
* *
* Compares two regions of memory longer than 64K. *
* *
* ENTRY: *
* *
* buf1 - pointer to first region *
* buf2 - pointer to second region *
* n - length of regions *
* *
* EXIT: *
* *
* Returns 0 on match, negative if mismatch byte in buf1 is less than *
* corresponding byte in buf2, positive if vice versa. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int LFMEMCMP(void far *buf1, void far *buf2, unsigned long n)
{
unsigned char huge *temp1, huge *temp2;
int retval = 0;
unsigned int cmplen;
/* normalize far pointers and turn into huge pointers */
temp1 = normptr(buf1);
temp2 = normptr(buf2);
while (n > 0L)
{
cmplen = ((n > 65000L) ? 65000U : (unsigned int) n);
retval = FMEMCMP((void far *) temp1, (void far *) temp2, cmplen);
if (retval != 0)
{
return retval;
}
temp1 = normptr((unsigned char far *)(temp1 + cmplen));
temp2 = normptr((unsigned char far *)(temp2 + cmplen));
n -= cmplen;
}
return retval;
} /* end of LFMEMCMP() */
/***************************************************************************
* FUNCTION: LFMEMSET *
* *
* DESCRIPTION: *
* *
* Sets a region of memory longer than 64K to a particular value. *
* *
* ENTRY: *
* *
* s - pointer to region of memory *
* c - byte value to set memory to *
* n - length of region *
* *
* EXIT: *
* *
* Void. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
void LFMEMSET(void far *s, int c, unsigned long n)
{
unsigned char huge *temp;
unsigned int fill_len;
/* normalize far pointer and turn into huge pointer */
temp = normptr(s);
while (n > 0L)
{
fill_len = ((n > 65000L) ? 65000U : (unsigned int) n);
FMEMSET((void far *) temp, c, fill_len);
temp = normptr((unsigned char far *)(temp + fill_len));
n -= fill_len;
}
return;
} /* end of LFMEMSET() */
/***************************************************************************
* FUNCTION: FARINCWORDFILL *
* *
* DESCRIPTION: *
* *
* Fill a region of memory with incrementing word (16 bit) values. *
* Always starts at 0 value. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory *
* len - length of block, must be even *
* *
* EXIT: *
* *
* Void. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
void farincwordfill(unsigned char far *buffer, unsigned int len,
unsigned int start)
{
unsigned char huge *temp;
#ifndef INLINE_ASM
int loop;
unsigned int huge *filler;
unsigned int value;
#endif
/* turn length in bytes into length in words, convert pointer */
len /= 2;
temp = normptr(buffer);
#ifdef INLINE_ASM
ASM push ax /* preserve registers */
ASM push cx
ASM push di
ASM push es
ASM les di, [temp] /* load pointer into ES:DI */
ASM mov cx, [len] /* load length into CX */
ASM mov ax, [start] /* load starting value into AX */
loop2top:
ASM stosw /* store AX in memory, DI += 2 */
ASM inc ax /* increment AX */
ASM loop loop2top /* loop */
ASM pop es /* restore register values */
ASM pop di
ASM pop cx
ASM pop ax
#else
/* do the same thing in C */
for (loop = 0, filler = (unsigned int huge *) temp, value = start;
loop < len;
loop++, value++)
{
filler[loop] = value;
}
#endif
return;
} /* end of farincwordfill() */
/***************************************************************************
* FUNCTION: LFARINCWORDFILL *
* *
* DESCRIPTION: *
* *
* This function fills a block of memory longer than 64K with *
* incrementing word values. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory to fill *
* len - length of block *
* start - value at which incrementing words start *
* *
* EXIT: *
* *
* Void. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
void lfarincwordfill(unsigned char far *buffer, unsigned long len,
unsigned int start)
{
unsigned int fill_len;
unsigned char huge *temp;
unsigned int value;
/* normalize far pointer and turn into huge pointer */
temp = normptr(buffer);
value = start;
while (len > 0L)
{
fill_len = ((len > 65000L) ? 65000U : (unsigned int) len);
farincwordfill((void far *) temp, fill_len, value);
temp = normptr((unsigned char far *)(temp + fill_len));
len -= fill_len;
value += (fill_len / 2);
}
return;
} /* end of lfarincwordfill() */
/***************************************************************************
* FUNCTION: FARINCWORDCHECK *
* *
* DESCRIPTION: *
* *
* Scans a block of memory to make sure contents are incrementing *
* word values. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory *
* len - length of block of memory, must be even *
* *
* EXIT: *
* *
* Returns 0 if contents are OK, nonzero if mismatch found. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int farincwordcheck(unsigned char far *buffer, unsigned int len,
unsigned int start)
{
int retval = 0;
unsigned char huge *temp;
#ifndef INLINE_ASM
int loop;
unsigned int huge *filler;
unsigned int value;
#endif
/* convert length in bytes to length in words, convert pointer */
len /= 2;
temp = normptr(buffer);
#ifdef INLINE_ASM
ASM push ax /* preserve register values */
ASM push bx
ASM push cx
ASM push si
ASM push ds
ASM lds si, [temp] /* load pointer into DS:SI */
ASM mov cx, [len] /* load length into CX */
ASM mov bx, [start] /* load starting value into BX */
ASM dec bx /* decrement BX, prep for loop */
loop3top:
ASM inc bx /* increment BX to next value */
ASM lodsw /* load next word into AX */
ASM cmp ax, bx /* compare word in AX and BX */
ASM loope loop3top /* loop while words are equal */
ASM je done /* exited loop -- if last cmp */
/* was equal, jump to end, else */
ASM mov WORD PTR [retval], 1 /* mismatch, set nonzero retval */
done:
ASM pop ds /* restore register values */
ASM pop si
ASM pop cx
ASM pop bx
ASM pop ax
#else
/* do the same thing in C */
for (loop = 0, filler = (unsigned int huge *) temp, value = start;
loop < len;
loop++, value++)
{
if (filler[loop] != value)
{
retval = 1;
break;
}
}
#endif
return retval;
} /* end of farincwordcheck() */
/***************************************************************************
* FUNCTION: LFARINCWORDCHECK *
* *
* DESCRIPTION: *
* *
* This function checks a block of memory longer than 64K for *
* incrementing word values. *
* *
* ENTRY: *
* *
* buffer - pointer to block of memory to check *
* len - length of block *
* start - value at which incrementing words start *
* *
* EXIT: *
* *
* Returns 0 if contents are OK, nonzero if mismatch found. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int lfarincwordcheck(unsigned char far *buffer, unsigned long len,
unsigned int start)
{
int retval;
unsigned int checklen;
unsigned char huge *temp;
unsigned int value;
/* normalize far pointer and turn into huge pointer */
temp = normptr(buffer);
value = start;
while (len > 0L)
{
checklen = ((len > 65000L) ? 65000U : (unsigned int) len);
if ((retval = farincwordcheck((void far *) temp, checklen, value)) != 0)
{
return retval;
}
temp = normptr((unsigned char far *)(temp + checklen));
len -= checklen;
value += (checklen / 2);
}
return retval;
} /* end of lfarincwordcheck() */
/***************************************************************************
* FUNCTION: GET_TICK *
* *
* DESCRIPTION: *
* *
* Retrieves the current timer count via BIOS call. For use when *
* timing copies. The timer ticks 18.2 times per second. The value *
* returned by this function has a jitter of -0,+(1/18.2) seconds. *
* *
* ENTRY: *
* *
* Void. *
* *
* EXIT: *
* *
* Returns the timer count. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
unsigned long get_tick(void)
{
unsigned long retval;
#ifdef INLINE_ASM
ASM push cx /* push register values */
ASM push dx
ASM xor ah, ah /* AH = 00h, get count call */
ASM int 1Ah /* make call */
ASM mov WORD PTR [retval + 2], cx /* save returned value */
ASM mov WORD PTR [retval], dx
ASM pop dx
ASM pop cx
#else
union REGS r;
/* do the same thing in C */
r.h.ah = 0x0;
int86(0x1A, &r, &r);
retval = r.x.cx;
retval <<= 16;
retval |= r.x.dx;
#endif
return retval;
} /* end of get_tick() */
/***************************************************************************
* FUNCTION: NORMPTR *
* *
* DESCRIPTION: *
* *
* Normalizes a far pointer -- reduces the offset to the smallest *
* possible value (somewhere between 0 and 0xF) by adding to the *
* segment. *
* *
* ENTRY: *
* *
* norm - pointer to be normalized *
* *
* EXIT: *
* *
* Returns normalized pointer. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
unsigned char huge *normptr(unsigned char far *norm)
{
unsigned char huge *retval = (unsigned char huge *) norm;
#ifdef INLINE_ASM
ASM push cx /* preserve register values */
ASM push di
ASM push si
ASM mov si, WORD PTR [retval] /* load offset into SI */
ASM mov di, si /* load offset into DI too */
ASM mov cl, 4 /* load 4 into CL */
ASM shr di, cl /* shift DI right by 4, which */
/* converts it to a segment */
ASM add WORD PTR [retval + 2], di /* add to segment in pointer */
ASM and si, 0Fh /* zero all but lowest nibble */
/* of offset */
ASM mov WORD PTR [retval], si /* put offset back in pointer */
ASM pop si /* restore register values */
ASM pop di
ASM pop cx
#else
unsigned int segment, offset;
/* do the same thing in C -- extract segment and offset from pointer */
segment = FP_SEG(retval);
offset = FP_OFF(retval);
/* add high three nibbles of offset to segment */
segment += (offset >> 4);
/* preseve only lowest nibble of offset */
offset &= 0xF;
/* reconstruct pointer from modified segment and offset */
retval = MK_FP(segment, offset);
#endif
return retval;
} /* end of normptr() */
/*
** The following group of functions is the same in spirit as the preceding
** group, but equivalents already exist in the libraries of some compilers.
** These functions are only used if the symbol NO_FFUNC is defined, which
** should only be done when the compiler's library does not already contain
** equivalent functions.
*/
/***************************************************************************
* FUNCTION: FMEMCMP *
* *
* DESCRIPTION: *
* *
* A replacement _fmemcmp() function for compilers which do not have *
* it in their libraries. Compares two regions of memory. *
* *
* ENTRY: *
* *
* buf1 - pointer to first region *
* buf2 - pointer to second region *
* n - length of regions *
* *
* EXIT: *
* *
* Returns 0 on match, negative if mismatch byte in buf1 is less than *
* corresponding byte in buf2, positive if vice versa. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
int Fmemcmp(void far *buf1, void far *buf2, unsigned int n)
{
unsigned char huge *temp1, huge *temp2;
int retval = 0;
#ifndef INLINE_ASM
int loop;
#endif
/* normalize pointers */
temp1 = normptr((unsigned char far *) buf1);
temp2 = normptr((unsigned char far *) buf2);
#ifdef INLINE_ASM
ASM push cx /* preserve register values */
ASM push di
ASM push si
ASM push ds
ASM push es
ASM lds si, [temp1] /* load first pointer in DS:SI */
ASM les di, [temp2] /* load second pointer in ES:DI */
ASM mov cx, [n] /* load length in CX */
ASM repz cmpsb /* compare while equal */
ASM jcxz alldone /* if CX is 0, all were equal */
ASM ja higher /* not equal, set return value */
ASM mov WORD PTR [retval], -1
ASM jmp alldone
higher:
ASM mov WORD PTR [retval], 1
alldone:
ASM pop es /* restore register values */
ASM pop ds
ASM pop si
ASM pop di
ASM pop cx
#else
/* do the same thing in C */
for (loop = 0; loop < n; loop++, temp1++, temp2++)
{
if (*temp1 == *temp2)
{
continue;
}
retval = (int) (*temp1 - *temp2);
break;
}
#endif
return retval;
} /* end of Fmemcmp() */
/***************************************************************************
* FUNCTION: FMEMSET *
* *
* DESCRIPTION: *
* *
* A replacement _fmemset() function for compilers which do not have *
* it in their libraries. Sets a region of memory to a particular *
* value. *
* *
* ENTRY: *
* *
* s - pointer to region of memory *
* c - byte value to set memory to *
* n - length of region *
* *
* EXIT: *
* *
* Returns s. *
* *
* CONSTRAINTS/SIDE EFFECTS: *
* *
***************************************************************************/
void Fmemset(void far *s, int c, unsigned int n)
{
unsigned char huge *temp;
/* normalize pointer */
temp = normptr((unsigned char far *) s);
#ifdef INLINE_ASM
/* if length is odd, use slower way */
if ((n % 2) == 1)
{
ASM push ax /* preserve register values */
ASM push cx
ASM push di
ASM push es
ASM les di, [temp] /* load pointer into ES:DI */
ASM mov al, BYTE PTR [c] /* load value into AL */
ASM mov cx, [n] /* load length into CX */
ASM rep stosb /* store value in memory */
ASM pop es /* restore register values */
ASM pop di
ASM pop cx
ASM pop ax
}
else
{
/* otherwise use faster way, storing entire words at once */
/* convert length in bytes to length in words */
n /= 2;
ASM push ax /* preserve register values */
ASM push cx
ASM push di
ASM push es
ASM les di, [temp] /* load pointer into ES:DI */
ASM mov al, BYTE PTR [c] /* load value into AL */
ASM mov ah, al /* load value into AH too */
ASM mov cx, [n] /* load length into CX */
ASM rep stosw /* store value in memory by words */
ASM pop es /* restore register values */
ASM pop di
ASM pop cx
ASM pop ax
}
#else
/* do the same thing in C */
for (; n; n--, temp++)
{
*temp = c;
}
#endif
return;
} /* end of Fmemset() */