home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Zodiac Super OZ
/
MEDIADEPOT.ISO
/
FILES
/
13
/
FREELI20.ZIP
/
386lib2.asx
< prev
next >
Wrap
Text File
|
1996-07-01
|
64KB
|
2,409 lines
~~~C_STR1
Ideal
Public strlen,strcpy,strcat,strcmp
Model Tiny
CodeSeg
P386
;****************** strlen() -- Get length of string
;int strlen(char *strp);
strp equ bp+4
Proc strlen
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
p1_loop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p1_loop
sub si,[strp] ;AX = length
dec si
xchg ax,si
pop si ;Restore SI
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlen
;****************** strcpy() -- Copy a string
;void strcpy(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcpy
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str2] ;SI = source
mov di,[str1] ;DI = destination
p2_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p2_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcpy
;****************** strcat() -- Concatenate strings
;void strcat(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcat
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov si,[str1] ;SI = destination
p3_cloop: lodsb ;Load char
test al,al ;Loop while not zero
jnz p3_cloop
mov di,si ;DI = destination
mov si,[str2] ;SI = source
dec di
p3_loop: lodsb ;Load char
mov [di],al ;Store char
inc di
test al,al ;Loop while not zero
jnz p3_loop
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP strcat
;****************** strcmp() -- Compare strings
;void strcmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc strcmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p4_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,ah ;Not equal?
jne p4_nope
test al,al ;Loop while not zero
jnz p4_loop
xor ax,ax ;Equal, return 0
p4_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p4_nope: sub al,ah ;Not equal, return difference
cbw ;in first unequal position
jmp p4_done
EndP strcmp
End
~~~C_STR2
Ideal
Extrn strlen:near
Public strchr,strstr
Model Tiny
CodeSeg
P386
;****************** strchr() -- Search string for char
;int strchr(char *strp, int chr);
strp equ bp+6
chr equ bp+4
Proc strchr
push bp ;Set up stack frame
mov bp,sp
push si ;Save SI
mov si,[strp] ;SI = string pointer
mov ah,[chr] ;AH = char
p1_loop: lodsb ;Load char
test al,al ;Null, not found
jz p1_nope
cmp al,ah ;Loop while not equal
jne p1_loop
sub si,[strp] ;AX = position of char
dec si
xchg ax,si
p1_done: pop si ;Restore SI
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP strchr
;****************** strstr() -- Search string for substring
;int strstr(char *strp, char *subp);
strp equ bp+6
subp equ bp+4
Proc strstr
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov si,[strp] ;SI = string pointer
mov bx,[subp] ;BX = substring pointer
push bx ;Get length of substring
call strlen ;into DX
xchg dx,ax
mov ah,[bx] ;AH = first char
p3_loop: lodsb ;Load char
test al,al ;Null, not found
jz p3_nope
cmp al,ah ;Loop while not equal
jne p3_loop
mov cx,dx ;CX = length
mov di,bx ;DI = substring
push si ;Save SI
dec si ;Push back char
repe cmpsb ;Compare strings
pop si ;Restore SI
jne p3_loop ;Loop if not equal
sub si,[strp] ;AX = position of char
dec si
mov es,si ;Sneaky: save it in ES
p3_done: popa ;Restore registers
mov ax,es ;Return value in AX
pop es
pop bp ;Delete stack frame
ret 4 ;Return
p3_nope: mov ax,-1 ;Not found, return -1
mov es,ax
jmp p3_done
EndP strstr
End
~~~C_STR3
Ideal
Public stricmp,strlwr,strupr
Model Tiny
CodeSeg
P386
;****************** stricmp() -- Compare strings, case insensitive
;void stricmp(char *str1, char *str2);
str1 equ bp+6
str2 equ bp+4
Proc stricmp
push bp ;Set up stack frame
mov bp,sp
push si di ;Save registers
mov si,[str1] ;SI = source
mov di,[str2] ;DI = destination
p1_loop: lodsb ;Load char 1
mov ah,[di] ;Load char 2
inc di
cmp al,'a' ;Convert AL to uppercase
jb p1_setAH
cmp al,'z'
ja p1_setAH
sub al,20h
p1_setAH: cmp ah,'a' ;Convert AH to uppercase
jb p1_comp
cmp ah,'z'
ja p1_comp
sub ah,20h
p1_comp: cmp al,ah ;Equal?
jne p1_nope
test al,al ;Loop while not zero
jnz p1_loop
inc ax ;Equal, return 1
p1_done: pop di si ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_nope: xor ax,ax ;Not equal, return 0
jmp p1_done
EndP stricmp
;****************** strlwr() -- Convert string to lowercase
;int strlwr(char *strp);
strp equ bp+4
Proc strlwr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_done
cmp al,'A' ;Check for uppercase
jb p2_loop
cmp al,'Z'
ja p2_loop
add al,20h ;Convert to lowercase
mov [si-1],al ;Store char
jmp p2_loop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strlwr
;****************** strupr() -- Convert string to uppercase
;int strupr(char *strp);
strp equ bp+4
Proc strupr
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
p3_loop: lodsb ;Load char
test al,al ;Check for null
jz p3_done
cmp al,'a' ;Check for lowercase
jb p3_loop
cmp al,'z'
ja p3_loop
sub al,20h ;Convert to uppercase
mov [si-1],al ;Store char
jmp p3_loop
p3_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strupr
End
~~~C_STR4
Ideal
Public strrtrim,strltrim
Model Tiny
CodeSeg
P386
;****************** strrtrim() -- Trim trailing spaces off a string
;int strrtrim(char *strp);
strp equ bp+4
Proc strrtrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI = string pointer
mov di,si ;DI = SI
p1_loop: lodsb ;Load char
test al,al ;Check for null
jz p1_done
cmp al,' ' ;Check for space
je p1_loop
mov di,si ;Set pointer
jmp p1_loop
p1_done: mov [byte di+1],al ;Terminate string
popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strrtrim
;****************** strltrim() -- Trim leading spaces off a string
;int strltrim(char *strp);
strp equ bp+4
Proc strltrim
push bp ;Set up stack frame
mov bp,sp
pusha ;Save registers
mov si,[strp] ;SI, DI = string pointer
mov di,si
p2_loop: lodsb ;Load char
test al,al ;Check for null
jz p2_cont
cmp al,' ' ;Loop while space
je p2_loop
p2_cont: dec si ;Move back one char
cmp si,di ;No spaces, quit
je p2_done
p2_cloop: lodsb ;Shift the string over
mov [di],al
inc di
test al,al
jnz p2_cloop
p2_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP strltrim
End
~~~C_MEM1
Ideal
Public memcpy,memset
Model Tiny
CodeSeg
P386
;****************** memcpy() -- Copy memory block
;void memcpy(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcpy
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
cmp di,si ;Make forward moves
jb p1_go ;in reverse
je p1_done
std ;Set direction flag
add si,cx ;Move offsets to end
add di,cx
dec si
dec di
p1_go: rep movsb ;Copy memory
p1_done: cld ;Clear direction flag
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcpy
;****************** memset() -- Set memory block
;void memset(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memset
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pusha
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
rep stosb ;Set memory
popa ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memset
End
~~~C_MEM2
Ideal
Public memcmp,memchr
Model Tiny
CodeSeg
P386
;****************** memcmp() -- Compare memory blocks
;void memcmp(void *p1, void *p2, int nbytes);
p1 equ bp+8
p2 equ bp+6
nbytes equ bp+4
Proc memcmp
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov si,[p2] ;SI = source
mov di,[p1] ;DI = destination
mov cx,[nbytes] ;CX = count
repe cmpsb ;Compare memory
mov ax,1 ;Assume equal
je p1_done ;Jump if equal
xor ax,ax ;Not equal, return 0
p1_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
EndP memcmp
;****************** memchr() -- Scan memory for char
;void memchr(void *ptr, int nbytes, int chr);
ptr equ bp+8
nbytes equ bp+6
chr equ bp+4
Proc memchr
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
push cx si di
push ds ;ES = DS
pop es
mov di,[ptr] ;DI = block
mov cx,[nbytes] ;CX = count
mov al,[chr] ;AL = char
repne scasb ;Scan memory
jne p2_nope ;Jump if not found
sub di,[ptr] ;AX = position of char
dec di
xchg ax,di
p2_done: pop di si cx ;Restore registers
pop es
pop bp ;Delete stack frame
ret 6 ;Return
p2_nope: mov ax,-1 ;Not found, return -1
jmp p2_done
EndP memchr
End
~~~C_ISRCH
Ideal
Public isearch
Model Tiny
P386
CodeSeg
;****************** isearch() -- Search a sorted array of integers
;int isearch(int *ary, int size, int elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc isearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
cmp ax,[elem] ;Check element
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
jmp p1_loop ;Loop back
p1_found: xchg ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP isearch
End
~~~C_LSRCH
Ideal
Public lsearch
Model Tiny
P386
CodeSeg
;****************** lsearch() -- Search a sorted array of longs
;int lsearch(long *ary, int size, long elem);
ary equ bp+10
size equ bp+8
elem equ bp+4
Proc lsearch
push bp ;Set up stack frame
mov bp,sp
push es ;Save registers
pushad
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
shl si,2
mov eax,[bx+si] ;Get element
shr si,2 ;Fix SI
cmp eax,[elem] ;Check element
je p1_done ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
jmp p1_loop ;Loop back
p1_done: mov es,si ;ES = result
popad ;Restore registers
mov ax,es ;AX = result
pop es ;Restore ES
pop bp ;Delete stack frame
ret 8 ;Return
p1_nope: mov si,-1 ;Not found, return -1
jmp p1_done
EndP lsearch
End
~~~C_XSRCH
Ideal
Public xsearch
Model Tiny
P386
CodeSeg
;****************** xsearch() -- Search sorted array, generalized
;int xsearch(void **ary, int size, void *elem, void *func);
ary equ bp+10
size equ bp+8
elem equ bp+6
func equ bp+4
Proc xsearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p3_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [word elem] ;Check element
call [word func]
test ax,ax
je p3_found ;Equal?
jl p3_less ;Too low?
p3_greater: mov di,si ;Set first half
mov si,cx
jmp p3_cont
p3_less: mov di,dx ;Set second half
inc si
p3_cont: cmp cx,dx ;Min = Max, done
je p3_nope
mov cx,si ;Set limits
mov dx,di
jmp p3_loop ;Loop back
p3_found: xchg ax,si ;AX = result
p3_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
p3_nope: mov ax,-1 ;Not found, return -1
jmp p3_done
EndP xsearch
End
~~~C_SSRCH
Ideal
Extrn strcmp:near
Public ssearch
Model Tiny
P386
CodeSeg
;****************** ssearch() -- Search a sorted array of strings
;int ssearch(char **ary, int size, char *elem);
ary equ bp+8
size equ bp+6
elem equ bp+4
Proc ssearch
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si di ;Save registers
mov bx,[ary] ;BX = array
xor cx,cx ;CX = lower limit
mov dx,[size] ;DX = upper limit
dec dx
p1_loop: mov si,cx ;SI = middle element
add si,dx
shr si,1
add si,si
mov ax,[bx+si] ;Get element
shr si,1 ;Fix SI
push ax [word elem] ;Check element
call strcmp
test ax,ax
je p1_found ;Equal?
jl p1_less ;Too low?
p1_greater: mov di,si ;Set first half
mov si,cx
jmp p1_cont
p1_less: mov di,dx ;Set second half
inc si
p1_cont: cmp cx,dx ;Min = Max, done
je p1_nope
mov cx,si ;Set limits
mov dx,di
dec di
jmp p1_loop ;Loop back
p1_found: xchg ax,si ;AX = result
p1_done: pop di si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
p1_nope: mov ax,-1 ;Not found, return -1
jmp p1_done
EndP ssearch
End
~~~C_ISORT
Ideal
Public isort
Model Tiny
P386
CodeSeg
;****************** isort() -- Sort an array of integers
;void isort(int *ary, int size);
ary equ bp+6
max equ bp+4
Proc isort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
cmp ax,[bx+di]
jle p1_done
xchg ax,[bx+di] ;Switch them
mov [bx+si],ax
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
cmp ax,[bx+si]
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
cmp ax,[bx+di]
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [word bx+si] ;Swap elements
push [word bx+di]
pop [word bx+si]
pop [word bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP isort
End
~~~C_LSORT
Ideal
Public lsort
Model Tiny
P386
CodeSeg
;****************** lsort() -- Sort an array of longs
;void lsort(long *ary, int size);
ary equ bp+6
max equ bp+4
num equ bp-4
Proc lsort
push bp ;Set up stack frame
mov bp,sp
pushad ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
shl dx,2
call p1_qsort
popad ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
je p1_ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,4
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov eax,[bx+si] ;Check them
cmp eax,[bx+di]
jle p1_done
xchg eax,[bx+di] ;Switch them
mov [bx+si],eax
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,3
shl si,2
mov eax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < EAX and
jge p1_loop2 ; SI < DX, advance SI
cmp eax,[bx+si]
jle p1_loop2
add si,4
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > EAX and
jle p1_cont2 ; DI > CX, advance DI
cmp eax,[bx+di]
jge p1_cont2
sub di,4
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [dword bx+si] ;Swap elements
push [dword bx+di]
pop [dword bx+si]
pop [dword bx+di]
add si,4 ;Advance SI, DI
sub di,4
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP lsort
End
~~~C_SSORT
Ideal
Extrn strcmp:near
Public ssort
Model Tiny
P386
CodeSeg
;****************** ssort() -- Sort an array of strings
;void ssort(char **ary, int size);
ary equ bp+6
max equ bp+4
Proc ssort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [word bx+di]
call strcmp
test ax,ax
jle p1_done
push [word bx+si] ;Switch them
push [word bx+di]
pop [word bx+si]
pop [word bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [word bx+si]
call strcmp
pop ax
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [word bx+di]
call strcmp
pop ax
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [word bx+si] ;Swap elements
push [word bx+di]
pop [word bx+si]
pop [word bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP ssort
End
~~~C_XSORT
Ideal
Public xsort
Model Tiny
P386
CodeSeg
;****************** xsort() -- Sort array, generalized
;void xsort(void **ary, int size, void *func);
ary equ bp+8
max equ bp+6
func equ bp+4
Proc xsort
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov bx,[ary] ;Call recursive routine
xor cx,cx
mov dx,[max]
dec dx
add dx,dx
call p1_qsort
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
p1_qsort: cmp cx,dx ;One element, return
jne $+3
ret
pusha
mov ax,dx ;Two elements, sort them
sub ax,cx
cmp ax,2
jne p1_cont
mov si,cx ;SI, DI = low, high
mov di,dx
mov ax,[bx+si] ;Check them
push ax [word bx+di]
call [word func]
test ax,ax
jle p1_done
push [word bx+si] ;Switch them
push [word bx+di]
pop [word bx+si]
pop [word bx+di]
jmp p1_done
p1_cont: mov si,cx ;AX = middle element
add si,dx
shr si,2
add si,si
mov ax,[bx+si]
mov si,cx ;SI = low, DI = high
mov di,dx
p1_loop: cmp si,dx ;While [BX+SI] < AX and
jge p1_loop2 ; SI < DX, advance SI
push ax ax [word bx+si]
call [word func]
pop ax
jle p1_loop2
add si,2
jmp p1_loop
p1_loop2: cmp di,cx ;While [BX+DI] > AX and
jle p1_cont2 ; DI > CX, advance DI
push ax ax [word bx+di]
call [word func]
pop ax
jge p1_cont2
sub di,2
jmp p1_loop2
p1_cont2: cmp si,di ;Hit in middle, recurse
jge p1_rec
push [word bx+si] ;Swap elements
push [word bx+di]
pop [word bx+si]
pop [word bx+di]
add si,2 ;Advance SI, DI
sub di,2
jmp p1_loop ;Loop back
p1_rec: cmp cx,si ;If first half isn't empty,
je p1_skip1 ;recurse to sort it
xchg dx,di
call p1_qsort
xchg dx,di
p1_skip1: cmp dx,di ;If second half isn't empty,
je p1_done ;recurse to sort it
xchg cx,si
call p1_qsort
xchg cx,si
p1_done: popa ;Restore registers
p1_ret: ret ;Return
EndP xsort
End
~~~C_LSHL
Ideal
Public lshl
Model Tiny
CodeSeg
P386
;****************** lshl() -- Shift long integer to the left
;long lshl(long x, int d); Included for compatibility.
x equ bp+6
d equ bp+4
Proc lshl
push bp ;Set up stack frame
mov bp,sp
push ebx cx ;Save registers
mov ebx,[x] ;EBX = x
mov cl,[d] ;CL = distance
shl ebx,cl ;Shift left
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop cx ebx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshl
End
~~~C_LSHR
Ideal
Public lshr
Model Tiny
CodeSeg
P386
;****************** lshr() -- Shift long integer to the right
;long lshr(long x, int d); Included for compatibility.
x equ bp+6
d equ bp+4
Proc lshr
push bp ;Set up stack frame
mov bp,sp
push ebx cx ;Save registers
mov ebx,[x] ;EBX = x
mov cl,[d] ;CL = distance
shr ebx,cl ;Shift right
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop cx ebx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP lshr
End
~~~C_LSAR
Ideal
Public lsar
Model Tiny
CodeSeg
P386
;****************** lsar() -- Shift long integer to the right, signed
;long lsar(long x, int d); Included for compatibility.
x equ bp+6
d equ bp+4
Proc lsar
push bp ;Set up stack frame
mov bp,sp
push ebx cx ;Save registers
mov ebx,[x] ;EBX = x
mov cl,[d] ;CL = distance
sar ebx,cl ;Shift right, signed
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop cx ebx ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP lsar
End
~~~C_LMUL
Ideal
Public lmul
Model Tiny
CodeSeg
P386
;****************** lmul() -- Multiply long integers
;long lmul(long x, long y); Included for compatibility.
x equ bp+8
y equ bp+4
Proc lmul
push bp ;Set up stack frame
mov bp,sp
push ebx ;Save registers
mov ebx,[x] ;EBX = x * y
imul ebx,[y]
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lmul
End
~~~C_LIMUL
Ideal
Public limul
Model Tiny
CodeSeg
P386
;****************** limul() -- Multiply long integers, signed
;long limul(long x, long y); Included for compatibility
x equ bp+8
y equ bp+4
Proc limul
push bp ;Set up stack frame
mov bp,sp
push ebx ;Save registers
mov ebx,[x] ;EBX = x * y
imul ebx,[y]
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP limul
End
~~~C_LDIV
Ideal
Public ldiv
Model Tiny
CodeSeg
P386
;****************** ldiv() -- Divide long integers
;long ldiv(long x, long y); Included for compatibility.
x equ bp+8
y equ bp+4
Proc ldiv
push bp ;Set up stack frame
mov bp,sp
push ebx ecx esi ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y
mov esi,[y]
xor edx,edx
div esi
mov edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop esi ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP ldiv
End
~~~C_LIDIV
Ideal
Public lidiv
Model Tiny
CodeSeg
P386
;****************** lidiv() -- Divide long integers, signed
;long lidiv(long x, long y); Included for compatibility.
x equ bp+8
y equ bp+4
Proc lidiv
push bp ;Set up stack frame
mov bp,sp
push ebx ecx esi ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y
mov esi,[y]
cdq
idiv esi
mov edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop esi ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lidiv
End
~~~C_LMOD
Ideal
Public lmod
Model Tiny
CodeSeg
P386
;****************** lmod() -- Modulo on long integers
;long lmod(long x, long y); Included for compatibility.
x equ bp+8
y equ bp+4
Proc lmod
push bp ;Set up stack frame
mov bp,sp
push ebx ecx esi ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y
mov esi,[y]
xor edx,edx
div esi
xchg edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,cx ;DX:AX = result
shr ecx,16
mov dx,cx
pop esi ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP lmod
End
~~~C_LIMOD
Ideal
Public limod
Model Tiny
CodeSeg
P386
;****************** limod() -- Modulo on long integers, signed
;long limod(long x, long y); Included for compatibility.
x equ bp+8
y equ bp+4
Proc limod
push bp ;Set up stack frame
mov bp,sp
push ebx ecx esi ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y
mov esi,[y]
cdq
idiv esi
xchg edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,cx ;DX:AX = result
shr ecx,16
mov dx,cx
pop esi ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP limod
End
~~~C_FIXMUL
Ideal
Public fixmul
Model Tiny
CodeSeg
P386
;****************** fixmul() -- Multiply fixed point numbers
;long fixmul(long x, long y); 48 clocks (486)
x equ bp+8
y equ bp+4
Proc fixmul
push bp ;Set up stack frame
mov bp,sp
push ebx ecx ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y (fixed point)
mov edx,[y]
imul edx
shrd eax,edx,16
mov edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixmul
End
~~~C_FIXDIV
Ideal
Public fixdiv
Model Tiny
CodeSeg
P386
;****************** fixdiv() -- Divide fixed point numbers
;long fixdiv(long x, long y); 57-86 clocks (486)
x equ bp+8
y equ bp+4
Proc fixdiv
push bp ;Set up stack frame
mov bp,sp
push ebx ecx esi ;Save registers
mov ecx,edx ;Save EDX:EAX
xchg ebx,eax
mov eax,[x] ;EAX = x / y (fixed point)
mov esi,[y]
cdq
shld edx,eax,16
shl eax,16
idiv esi
mov edx,ecx ;Restore EDX:EAX
xchg ebx,eax
xchg ax,bx ;DX:AX = result
shr ebx,16
mov dx,bx
pop esi ecx ebx ;Restore registers
pop bp ;Delete stack frame
ret 8 ;Return
EndP fixdiv
End
~~~C_TRIG
Ideal
Extrn fixdiv:near
Public sine, cosine, tangent, cotangent
Public secant, cosecant
Model Tiny
CodeSeg
P386
;****************** TaylorSine() -- Calculate sine by Taylor series
;long TaylorSine(long x); Returns value in EBX
; *──────────────────────────────────────────────────*
; │ x^3 x^5 x^7 x^9 │
; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
; │ 3 ! 5 ! 7 ! 9 ! │
; *──────────────────────────────────────────────────*
x equ bp+4
Proc TaylorSine
push bp ;Set up stack frame
mov bp,sp
push eax ecx edx esi ;Save registers
mov eax,[x] ;First term = x
xor ebx,ebx ;Result = 0
mov esi,1 ;Count = 1
TS_loop: add ebx,eax ;Add in term
imul [dword x] ;term = last-term * x^2
shrd eax,edx,16
imul [dword x]
shrd eax,edx,16
add esi,2 ;n = n + 2
mov ecx,esi ;ECX = n * (n - 1)
dec ecx
imul ecx,esi
cdq ;term = last-term * x^2 / n(n-1)
idiv ecx
neg eax ;Invert sign
test eax,eax ;Loop while not zero
jnz TS_loop
pop esi edx ecx eax ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP TaylorSine
Pi dd 0003243Fh ;Pi (3.243F6A88... hex)
TwoPi dd 0006487Fh ;Pi*2 (6.487ED511... hex)
HalfPi dd 00019220h ;Pi/2 (1.921FB544... hex)
;****************** sine() -- Trigonometric sine function
;long sine(long x);
x equ bp+4
Proc sine
push bp ;Set up stack frame
mov bp,sp
push ebx ;Save EBX
mov ebx,[x] ;EBX = x + Pi
add ebx,[Pi]
push ebx [TwoPi] ;Divide by 2*Pi
call fixdiv
movsx ebx,dx ;EBX = integer part
imul ebx,[TwoPi] ;Multiply by 2*Pi
neg ebx ;EBX = x - EBX
add ebx,[x]
push ebx ;Calculate sine
call TaylorSine
xchg ax,bx ;Result in DX:AX
shr ebx,16
mov dx,bx
pop ebx ;Restore EBX
pop bp ;Delete stack frame
ret 4 ;Return
EndP sine
;****************** cosine() -- Trigonometric cosine function
;long cosine(long x);
x equ bp+4
Proc cosine
push bp ;Set up stack frame
mov bp,sp
mov dx,[x+2] ;DX:AX = x
mov ax,[x]
add ax,[word HalfPi] ; x + Pi+2
adc dx,[word HalfPi+2]
push dx ax ;cos(x) = sin(x + Pi/4)
call sine
pop bp ;Delete stack frame
ret 4 ;Return
EndP cosine
;****************** tangent() -- Trigonometric tangent function
;long tangent(long x);
x equ bp+4
Proc tangent
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
push [dword x] ;CX:BX = sin(x)
call sine
mov cx,dx
xchg bx,ax
push [dword x] ;DX:AX = cos(x)
call cosine
push cx bx dx ax ;tan(x) = sin(x) / cos(x)
call fixdiv
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP tangent
;****************** cotangent() -- Trigonometric cotangent function
;long cotangent(long x);
x equ bp+4
Proc cotangent
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
push [dword x] ;CX:BX = sin(x)
call sine
mov cx,dx
xchg bx,ax
push [dword x] ;DX:AX = cos(x)
call cosine
push dx ax cx bx ;cot(x) = cos(x) / sin(x)
call fixdiv
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP cotangent
;****************** secant() -- Trigonometric secant function
;long secant(long x);
x equ bp+4
Proc secant
push bp ;Set up stack frame
mov bp,sp
push [dword x] ;DX:AX = cos(x)
call cosine
push 1 0 dx ax ;sec(x) = 1 / cos(x)
call fixdiv
pop bp ;Delete stack frame
ret 4 ;Return
EndP secant
;****************** cosecant() -- Trigonometric cosecant function
;long cosecant(long x);
x equ bp+4
Proc cosecant
push bp ;Set up stack frame
mov bp,sp
push [dword x] ;DX:AX = cos(x)
call sine
push 1 0 dx ax ;csc(x) = 1 / sin(x)
call fixdiv
pop bp ;Delete stack frame
ret 4 ;Return
EndP cosecant
End
~~~C_FIXTOA
Ideal
Public fixtoa
Model Tiny
CodeSeg
P386
;****************** fixtoa() -- Convert fixed point number to string
;void fixtoa(int n, char *strp);
n equ bp+6
strp equ bp+4
Proc fixtoa
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov di,[strp] ;DI = string pointer
mov dx,[n+2] ;DX:AX = n
mov ax,[n]
test dx,dx ;Negative?
jge p1_noneg
mov [byte di],'-' ;Store minus sign
inc di
neg dx ;Make it positive
neg ax
sbb dx,0
p1_noneg: push dx ;Save DX
xor bx,bx ;Zero rem flag
add ax,ax ;Shift out high bit
adc bx,0 ;BX = rem flag
shr ax,1 ;Restore AX
mov cx,50000 ;AX = AX * 50000
mul cx
shr ax,15 ;AX = AX / 32768
shl dx,1
or ax,dx
pop dx ;Restore DX
push bx ax ;Save BX, AX
xchg dx,ax ;Integer part in AX
xor cx,cx ;Zero CX
mov si,10 ;SI = 10
p1_dloop: xor dx,dx ;Divide by 10
div si
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
inc cx
test ax,ax ;Loop back
jnz p1_dloop
p1_ploop: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploop ;Loop back
mov [byte di],'.' ;Store decimal point
inc di
pop ax bx ;Restore low data
xor dx,dx ;Zero DX
test bx,bx ;Check for high part
jz p1_nohigh
add ax,50000 ;Add in 50000
adc dx,0
p1_nohigh: mov si,10 ;SI = 10
mov cx,5 ;5 digits
jmp p1_skip1
p1_dloopb: xor dx,dx ;Zero DX
p1_skip1: div si ;Divide by 10
mov bl,dl ;Remainder in BL
add bl,30h ;Convert to digit
push bx ;Push digit
loop p1_dloopb ;Loop back
mov cx,5 ;5 digits
p1_ploopb: pop ax ;Pop digit
mov [di],al ;Store digit
inc di
loop p1_ploopb ;Loop back
mov [byte di],0 ;Add the null byte
p1_done: popa ;Restore registers
pop bp ;Delete stack frame
ret 6 ;Return
EndP fixtoa
End
~~~C_ATOFIX
Ideal
Public atofix
Model Tiny
CodeSeg
P386
;****************** atofix() -- Convert string to fixed point number
;long atofix(char *strp);
strp equ bp+4
Proc atofix
push bp ;Set up stack frame
mov bp,sp
push bx cx si di bp ;Save registers
mov si,[strp] ;SI = string
xor ax,ax ;AX = 0
xor bh,bh ;BH = 0
mov cx,10 ;CX = 10
p1_ploop: mov bl,[si] ;Load char
inc si
cmp bl,' ' ;Loop while char is space
je p1_ploop ;(20h, or 09h thru 0Dh)
cmp bl,9
jna p1_go
cmp bl,13
jbe p1_ploop
p1_go: xor bp,bp ;BP = 0
cmp bl,'+' ;If char = '+', ignore
je p1_loop
cmp bl,'-' ;If char <> '-', keep it
jne p1_skip
inc bp ;Set negative flag
p1_loop: mov bl,[si] ;Load char
inc si
p1_skip: xor dx,dx ;Clear DX
cmp bl,'.' ;Decimal point, continue
je p1_cont
cmp bl,'9' ;Not a digit, finish
ja p1_finish
sub bl,'0'
jc p1_finish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
jmp p1_loop ;Loop back
p1_cont: push ax ;Save integer part
xor ax,ax ;Zero AX
mov di,1 ;DI = 1
p1_floop: mov bl,[si] ;Load char
inc si
cmp bl,'9' ;Not a digit, finish
ja p1_ffinish
sub bl,'0'
jc p1_ffinish
mul cx ;Multiply by 10
add ax,bx ;Add in digit...
adc dx,0
imul di,10 ;Multiply divisor by 10
jnc p1_floop ;Loop while < 5 digits
shr dx,1 ;5 digits, divide by 2
rcr ax,1 ;and set DI to 50000
mov di,50000 ;instead of 100000
p1_ffinish: xchg dx,ax ;Multiply by 65536
xor ax,ax
div di ;Divide by 10^digits
xchg dx,ax ;Fractional part in DX
pop ax ;Restore integer part
p1_finish: xchg dx,ax ;DX:AX = number
dec bp ;Positive, don't negate
jl p1_done
neg dx ;Negate the result
neg ax
sbb dx,0
p1_done: pop bp di si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP atofix
End
~~~C_BITS
Ideal
Public bitcnt,highbit
Model Tiny
P386
CodeSeg
;****************** bitcnt() -- Count set bits in integer
;int bitcnt(int x);
x equ bp+4
Proc bitcnt
push bp ;Set up stack frame
mov bp,sp
push bx cx ;Save registers
xor cx,cx ;CX = 0
mov ax,[x] ;AX = number
test ax,ax ;Zero?
jz p1_done
p1_loop: mov bx,ax ;Kill last bit
dec bx
and ax,bx
loopnz p1_loop ;Loop while not zero
p1_done: sub ax,cx ;Negative of CX
pop cx bx ;Restore registers
pop bp ;Delete stack frame
ret 2 ;Return
EndP bitcnt
;****************** highbit() -- Find high bit in integer
;int highbit(int x); returns -1 if it was zero
x equ bp+4
Proc highbit
push bp ;Set up stack frame
mov bp,sp
bsr ax,[x] ;Scan for bit
jnz $+5 ;No bit set?
mov ax,-1 ;Return -1
pop bp ;Delete stack frame
ret 2 ;Return
EndP highbit
End
~~~C_SQRT
Ideal
Public sqrt
Model Tiny
P386
CodeSeg
;****************** sqrt() -- Returns the square root of a
; long. Result is an integer.
;int sqrt(long num); 60-350 clocks (486)
num equ bp+4
Proc sqrt
push bp ;Set up stack frame
mov bp,sp
push cx dx ;Save registers
mov ax,[num] ;DX:AX = num
mov dx,[num+2]
mov cx,32 ;32 bits
p1_bloop: add ax,ax ;Find the highest set bit
adc dx,dx
jc p1_gotbit
loop p1_bloop
p1_gotbit: mov ax,1 ;CX = first guess 2^(log2(n)/2)
shr cx,1
shl ax,cl
xchg cx,ax
p1_loop: mov ax,[num] ;DX:AX = num
mov dx,[num+2]
div cx ;AX = num/guess
add cx,ax ;CX = (guess+(num/guess))/2
shr cx,1
sub ax,cx ;If the difference is 1
cmp ax,1 ;or less, then done
ja p1_loop ;Loop back
xchg ax,cx ;AX = result
pop dx cx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP sqrt
End
~~~C_ROMAN
Ideal
Public roman
Model Tiny
CodeSeg
P386
;****************** roman() -- Convert integer to Roman Numerals
num equ bp+6
buf equ bp+4
Proc roman
push bp ;Set up stack frame
mov bp,sp
pusha ;Save all registers
mov di,[buf] ;DI = buffer
mov dx,[num] ;DX = number
mov si,offset RNTbl_1 ;SI, BX = tables
mov bx,offset RNTbl_2
p1_loop: lodsw ;Load size
test ax,ax ;Done?
jz p1_done
p1_iloop: cmp dx,ax
jl p1_lb
mov cx,[bx] ;AX = code
mov [di],cl ;Store first char
inc di
cmp ch,'.' ;If second char, then
je p1_ilb ; store second char
mov [di],ch
inc di
p1_ilb: sub dx,ax ;Reduce number
jmp p1_iloop ;Loop back
p1_lb: add bx,2 ;Advance pointer
jmp p1_loop ;Loop back
p1_done: mov [di],al ;Terminate string
popa ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP roman
RNTbl_1 dw 1000,900,500,400,100
dw 90,50,40,10,9,5,4,1,0
RNTbl_2 db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
End
~~~C_CRC16
Ideal
Public crc16
Model Tiny
CodeSeg
P386
;****************** crc16() -- Calculate 16-bit CRC
;int crc16(void *ptr, int cnt)
ptr equ bp+6
cnt equ bp+4
Proc crc16
push bp ;Set up stack frame
mov bp,sp
push bx cx dx si ;Save registers
mov si,[ptr] ;SI = pointer
mov bx,[cnt] ;BX = count
xor dx,dx ;Start with 0
p1_loop: lodsb ;Load byte
xor dh,al ;XOR into result
mov cx,8 ;8 bits
p1_iloop: add dx,dx ;Shift left
jnc $+5 ;If bit = 1, then
xor dx,1021h ;XOR in CRC value
loop p1_iloop ;Loop back
dec bx ;Byte loop
jnz p1_loop
xchg dx,ax ;Result in AX
p1_done: pop si dx cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP crc16
End
~~~C_CRC32
Ideal
Public crc32
Model Tiny
CodeSeg
P386
;****************** crc32() -- Calculate 32-bit CRC
;long crc32(void *ptr, int cnt)
ptr equ bp+6
cnt equ bp+4
Proc crc32
push bp ;Set up stack frame
mov bp,sp
push bx cx si di ;Save registers
mov si,[ptr] ;SI = pointer
mov bx,[cnt] ;BX = count
xor dx,dx ;Start with 0
xor di,di
p1_loop: lodsb ;Load byte
xor dh,al ;XOR into result
mov cx,8 ;8 bits
p1_iloop: add di,di ;Shift left
adc dx,dx
jnc $+8 ;If bit = 1, then
xor dx,04C1h ;XOR in CRC value
xor di,1DB7h
loop p1_iloop ;Loop back
dec bx ;Byte loop
jnz p1_loop
xchg di,ax ;Result in DX:AX
p1_done: pop di si cx bx ;Restore registers
pop bp ;Delete stack frame
ret 4 ;Return
EndP crc32
End