home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QBasic & Borland Pascal & C
/
Delphi5.iso
/
C
/
Samples
/
CASM.ARJ
/
STRINGS.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-05-18
|
14KB
|
709 lines
;_ strings.asm Tue May 17 1988 Modified by: Walter Bright */
;Copyright (C) 1985-1988 by Northwest Software
;All Rights Reserved
;Written by Walter Bright
include macros.asm
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare a string.
; Use:
; int strcmp(s1,s2)
; Returns:
; > 0 if s1 > s2
; = 0 if s1 == s2
; < 0 if s1 < s2
;
ifdef Astrcmp
begcode strcmp
c_public strcmp
func strcmp
mov BX,SP
if SPTR
.save SI
mov DX,DI ;save DI
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P-2+2[BX] ;get source pointer (s2)
mov SI,P-2[BX] ;get destination pointer (s1)
else
.save <SI,DI>
mov DX,DS
les DI,SS:P-2+4[BX] ;get source pointer (s2)
lds SI,SS:P-2[BX] ;get destination pointer (s1)
endif
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb
not CX ;CX = string length of s2
sub DI,CX ;point DI back to beginning
repe cmpsb ;compare string
je L1 ;strings are equal
if 0
jae L2 ;s1 < s2
inc AX ;s1 > s2
jmps L1
L2: dec AX ;AX = -1
else
sbb AX,AX
cmc
adc AX,0
endif
L1:
if SPTR
mov DI,DX
.restore SI
else
mov DS,DX
.restore <DI,SI>
endif
ret
c_endp strcmp
endcode strcmp
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare a string of at most n chars (unsigned).
; Use:
; int strncmp(s1,s2,n)
; Returns:
; > 0 if s1 > s2
; = 0 if s1 == s2
; < 0 if s1 < s2
;
ifdef Astrncmp
begcode strncmp
c_public strncmp
func strncmp
push BP
mov BP,SP
.save <SI,DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P+2[BP] ;get source pointer (s2)
mov SI,P[BP] ;get destination pointer (s1)
else
mov BX,DS
les DI,P+4[BP] ;get source pointer (s2)
lds SI,P[BP] ;get destination pointer (s1)
endif
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb
not CX ;CX = string length of s2
sub DI,CX ;point DI back to beginning
if SPTR
.if CX b P+4[BP], L5
mov CX,P+4[BP] ;CX = min(CX,n)
else
.if CX b P+8[BP], L5
mov CX,P+8[BP] ;CX = min(CX,n)
endif
L5: repe cmpsb ;compare string
je L3 ;strings are equal
if 0
jae L4 ;s1 < s2
inc AX ;s1 > s2
jmps L3
L4: dec AX ;AX = -1
else
sbb AX,AX
cmc
adc AX,0
endif
L3:
if LPTR
mov DS,BX
endif
.restore <DI,SI>
pop BP
ret
c_endp strncmp
endcode strncmp
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare an array of n bytes (unsigned).
; Use:
; int memcmp(s1,s2,n)
; Returns:
; > 0 if s1 > s2
; = 0 if s1 == s2
; < 0 if s1 < s2
;
ifdef Amemcmp
begcode memcmp
c_public memcmp
func memcmp
push BP
mov BP,SP
.save <SI,DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P+2[BP] ;get source pointer (s2)
mov SI,P[BP] ;get destination pointer (s1)
else
mov BX,DS
les DI,P+SIZEPTR[BP] ;get source pointer (s2)
lds SI,P[BP] ;get destination pointer (s1)
endif
mov CX,P+SIZEPTR+SIZEPTR[BP] ;CX = n
clr AX
cld
repe cmpsb ;compare string
je L3 ;strings are equal
if 0
jae L4 ;s1 < s2
inc AX ;s1 > s2
jmps L3
L4: dec AX ;AX = -1
else
sbb AX,AX
cmc
adc AX,0
endif
L3:
if LPTR
mov DS,BX
endif
.restore <DI,SI>
pop BP
ret
c_endp memcmp
endcode memcmp
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Calculate length of string and return it.
; int strlen(s)
ifdef Astrlen
begcode strlen
c_public strlen
func strlen
mov BX,SP
mov DX,DI ;save DI
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P-2[BX] ;DI = s
else
les DI,SS:P-2[BX]
endif
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb
mov AX,CX
not AX ;AX = string length
dec AX
mov DI,DX
ret
c_endp strlen
endcode strlen
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cat s2 to s1 till a zero byte.
; Use:
; char *strcat(s1,s2)
; Returns:
; s1
;
ifdef Astrcat
begcode strcat
c_public strcat
func strcat
push BP
mov BP,SP
.save <SI,DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov SI,P+2[BP] ;get source pointer
mov DI,P[BP] ;get destination pointer
else
push DS
les DI,P[BP] ;get destination pointer (s1)
endif
mov BX,DI ;save it
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb ;find end of s1
dec DI ;DI -> EOS of s1
mov DX,DI
if SPTR
mov DI,SI ;DI -> s2
else
les DI,P+4[BP] ;ES:DI = s2
endif
mov CX,-1
repne scasb
not CX ;CX = strlen(s2) + 1 (for EOS)
mov DI,DX ;DI -> end of s1
if SPTR
rep movsb ;transfer bytes (including EOS)
mov AX,BX ;return pointer to s1
else
mov ES,P+2[BP] ;ES:DI -> end of s1
lds SI,P+4[BP] ;get source pointer (s2)
rep movsb ;transfer bytes (including EOS)
ifdef MSC
mov AX,BX
mov DX,ES ;DX,AX points to s1
else
mov AX,ES ;AX,BX points to s1
endif
pop DS
endif
.restore <DI,SI>
pop BP
ret
c_endp strcat
endcode strcat
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Cat s2 to s1 till a zero byte or n bytes are copied.
; Use:
; char *strncat(char *s1,char *s2,unsigned n)
; Returns:
; s1
;
ifdef Astrncat
begcode strncat
c_public strncat
func strncat
push BP
mov BP,SP
.save <SI,DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov SI,P+2[BP] ;get source pointer (s2)
mov DI,P[BP] ;get destination pointer (s1)
else
push DS
les DI,P[BP] ;get destination pointer (s1)
mov BX,DI ;set up offset of return value (s1)
endif
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb ;find end of s1
dec DI ;point at terminating 0
mov DX,DI ;save
if SPTR
mov DI,SI ;DI -> s2
else
les DI,P+SIZEPTR[BP] ;ES:DI -> s2
endif
mov CX,-1
repne scasb
not CX
dec CX ;CX = strlen(s2)
.if CX b P+SIZEPTR+SIZEPTR[BP], L6
mov CX,P+SIZEPTR+SIZEPTR[BP] ;CX = min(CX,n)
L6: mov DI,DX ;DI -> end of s1
if LPTR
mov ES,P+2[BP] ;ES = segment of s1
lds SI,P+SIZEPTR[BP] ;DS:SI -> s2
endif
rep movsb ;transfer bytes
stosb ;terminate with a 0
if SPTR
mov AX,P[BP] ;return pointer to s1
else
ifdef MSC
mov AX,BX
mov DX,ES ;DX,AX = s1
else
mov AX,ES ;AX,BX = s1
endif
pop DS
endif
.restore <DI,SI>
pop BP
ret
c_endp strncat
endcode strncat
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy s2 to s1 till a zero byte.
; Use:
; char *strcpy(s1,s2)
;
ifdef Astrcpy
begcode strcpy
c_public strcpy
func strcpy
if SPTR
mov BX,SP
.save SI
mov DX,DI
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P-2+2[BX] ;get source pointer (s2)
mov SI,DI ;save it
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb ;find end of s2
not CX ;CX = strlen(s2) + 1 (for EOS)
mov DI,P-2[BX] ;DI -> s1
mov AX,DI ;return value
rep movsb ;transfer bytes (including EOS)
mov DI,DX
.restore SI
else
mov BX,SP
.save <SI,DI>
les DI,SS:P-2+4[BX] ;ES:DI = s2
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb ;find end of s2
not CX ;CX = strlen(s2) + 1 (for EOS)
mov DX,DS
les DI,SS:P-2[BX]
lds SI,SS:P-2+4[BX]
mov AX,DI ;return value is s1
rep movsb
mov DS,DX
.restore <DI,SI>
mov DX,ES
endif
ret
c_endp strcpy
endcode strcpy
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy exactly n chars from s2 to s1, padding with nulls if necessary.
; Use:
; char *strncpy(s1,s2,n)
;
ifdef Astrncpy
begcode strncpy
c_public strncpy
func strncpy
push BP
mov BP,SP
.save <SI,DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P+2[BP] ;get source pointer
mov BX,DI ;save it
else
les DI,P+4[BP]
endif
clr AX ;scan for 0
mov CX,-1 ;largest possible string
cld ;direction flag = increment
repne scasb ;find end of s2
not CX ;CX = strlen(s2) + 1 (for EOS)
if SPTR
mov DX,P+4[BP] ;DX = n
else
mov DX,P+8[BP]
endif
.if DX ae CX, L7 ;if n >= strlen(s2) + 1
mov CX,DX ;CX = min(CX,n)
L7: sub DX,CX ;DX = # of nulls to pad
if SPTR
mov DI,P[BP] ;DI -> s1
mov SI,BX ;SI -> s2
else
push DS
les DI,P[BP]
mov BX,DI ;for return value
lds SI,P+4[BP]
endif
rep movsb ;transfer bytes (including EOS)
mov CX,DX ;# of nulls to pad
clr AL
rep stosb
if SPTR
mov AX,P[BP] ;return value
else
ifdef MSC
mov AX,BX
mov DX,ES
else
mov AX,ES
endif
pop DS
endif
.restore <DI,SI>
pop BP
ret
c_endp strncpy
endcode strncpy
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set n bytes in s to c.
; char *memset(char *p,int c,int n)
; Returns:
; p
ifdef Amemset
begcode memset
c_public memset
func memset
push BP
mov BP,SP
.save <DI>
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P[BP] ;p
mov AL,P+2[BP] ;c
mov CX,P+4[BP] ;n
cld
rep stosb
mov AX,P[BP] ;original value of p
else
les DI,P[BP] ;p
mov BX,DI
mov AL,P+4[BP] ;c
mov CX,P+6[BP] ;n
cld
rep stosb
ifdef MSC
mov AX,BX
mov DX,ES ;return original value of p in DX,AX
else
mov AX,ES ;return original value of p in AX,BX
endif
endif
.restore <DI>
pop BP
ret
c_endp memset
endcode memset
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Copy n bytes from p2 to p1.
; void *memcpy(void *p1,void *p2,n)
; Returns:
; p1
ifdef Amemcpy
c_public memcpy
begcode memcpy
c_public memmove ;alternate entry point
func memmove
c_endp memmove
func memcpy
mov BX,SP
if SPTR
mov CX,P-2+SIZEPTR+SIZEPTR[BX] ;CX = n
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DX,SI ;save SI
mov SI,P-2+SIZEPTR[BX] ;p2
mov AX,P-2[BX] ;p1
else
mov CX,SS:P-2+SIZEPTR+SIZEPTR[BX] ;CX = n
.save SI
mov DX,DS
lds SI,SS:P-2+SIZEPTR[BX] ;DS:SI = p2
les AX,SS:P-2[BX] ;ES:DI = p1
endif
mov BX,DI ;save DI
mov DI,AX ;AX = original offset value of p1
.if SI b DI, M1 ;if reverse copy is necessary
cld
shr CX,1
jz M2 ;if n is 0 or 1
rep movsw
M2: jnc M5 ;if n is even
movsb
M5:
if SPTR
mov SI,DX
else
mov DS,DX
mov DX,ES ;DX:AX = original value of p1
.restore SI
endif
mov DI,BX
ret
M1: add SI,CX
dec SI
add DI,CX
dec DI
std ;reverse direction of copy
shr CX,1
jnc M6
movsb
M6: jcxz M7
dec SI
dec DI
rep movsw
M7: cld
jmps M5
c_endp memcpy
endcode memcpy
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Return pointer to first occurrence of char c in string s.
; char *index(s,c)
; char *s,c;
ifdef Aindex
begcode strchr
c_public index,strchr
func strchr
c_endp strchr
func index
push BP
mov BP,SP
.save <DI>
cld
if SPTR
ife ESeqDS
mov AX,DS
mov ES,AX
endif
mov DI,P[BP] ;DI = s
else
les DI,P[BP] ;ES:DI = s
endif
clr AX
mov CX,-1
repne scasb
not CX ;CX = length of s (including NULL)
sub DI,CX ;DI = s
if SPTR
mov AL,P+2[BP] ;AL = c
else
mov AL,P+4[BP] ;AL = c
endif
repne scasb ;scan for c
mov AX,0 ;assume we didn't find it
if SPTR
jnz L8 ;didn't find it
mov AX,DI ;yes, found it
dec AX
else
ifdef MSC
cwd
jnz L8
mov DX,ES
mov AX,DI
dec AX
else
mov BX,AX
jnz L8
mov AX,ES
mov BX,DI
dec BX
endif
endif
L8: .restore <DI>
pop BP
ret
c_endp index
endcode strchr
endif
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Compare strings just like strcmp(), except that case is ignored.
ifdef Astrcmpl
begcode strcmpl
c_public strcmpl
func strcmpl
push BP
mov BP,SP
.save SI
if SPTR
mov SI,P[BP]
mov BX,P+SIZEPTR[BP]
else
push DS
lds SI,P[BP] ;DS:SI -> p1
les BX,P+SIZEPTR[BP] ;ES:BX -> p2
endif
cld
L1: lodsb ;AL = *p1++
if SPTR
mov CL,[BX]
else
mov CL,ES:[BX]
endif
inc BX ;CL = *p2++
.if AL ne CL, L2 ;strings are different at this char
tst AL ;end of string?
jnz L1 ;no
jmps L3
L2: ;Perhaps when converted to lower case, they will be the same
.if AL b 'A', L4
.if AL a 'Z', L4
add AL,'a' - 'A' ;convert AL to lower case
L4: .if CL b 'A', L5
.if CL a 'Z', L5
add CL,'a' - 'A' ;convert CL to lower case
L5: .if AL e CL, L1 ;same now, so continue looping
L3: clr AH
clr CH
sub AX,CX
if LPTR
pop DS
endif
.restore SI
pop BP
ret
c_endp strcmpl
endcode strcmpl
endif
end