📄 dstr003.asm
字号:
;************************************************************************
;* MODULE INFORMATION*
;**********************
;* FILE NAME: dstr003.asm
;* SYSTEM NAME: devlib
;* ORIGINAL AUTHOR(S): Paul Lemmers
;* VERSION NUMBER:
;* CREATION DATE: 1990/8/14
;*
;* DESCRIPTION: Contains dev_stricmp
;*
;************************************************************************
;* CHANGES INFORMATION **
;************************
;* REVISION: $Revision: 1.1 $
;* WORKFILE: $Workfile: dstr003.asm $
;* LOGINFO: $Log: D:/CPROG/MYDEV/DEVLIB/VCS/DSTR003.ASV $
;*
;* Rev 1.1 17 Dec 1990 14:35:18 PAUL
;* os2def.h changes
;*
;* Rev 1.0 14 Aug 1990 14:41:06 PAUL
;* Initial revision.
;************************************************************************/
;
INCLUDE cdev.inc
_TEXT SEGMENT
;************************************************************************
;* NAME: dev_stricmp
;* SYNOPSIS: int dev_stricmp(char far *p1, char far *p2);
;* DESCRIPTION: See C-runtime stricmp
;* UNMODIFIED REGISTERS:
;* ds bp si di
;* RETURNS: < 0 : p1 < p2
;* 0 : p1 == p2
;* > 0 : p1 > p2
; TIMING:
;* This function is full of timing tricks.
;* First:
;* The two stage compare (with scasb) is more expensive
;* than this implementation. (two stage included)
;* For equal characters it is 23*N (8+7+8 {scasb, jz, loope}
;* two stage) against 12*N (2+3+7 {or, jz, jz} one stage).
;* Second:
;* It has the "premature" compare of unconverted characters,
;* this may speed up matching non letter and uppercase compares.
;* It is however responsable for the dramatic difference between
;* the two stage and the one stage implementation.
;* Which would be: 16*N (8+8 scasb and loope for two stage) and
;* 12*N (2+3+7 for one stage).
;* Third:
;* The conversion to lowercase. If YOU can find the time to
;* tell me why your method is better than this one (from MSC)
;* then please do so.....
;* What about the traditional cmp 'a','z', mind you, at least
;* one char must be converted. And if we are not in the
;* 'A'..'Z','a'..'z' range then we don't have to compare at
;* all....
;************************************************************************
PUBLIC _dev_stricmp
p1 = 4
p2 = 8
_dev_stricmp PROC NEAR
push bp
mov bp,sp
push ds
mov dx,si
lds si,[bp+p2]
les bx,[bp+p1] ; get ptr to string
mov al,0FFh
; The $L000 label can be reached from above or two conditional
; jumps on zero after comparing ah and al. ==>
; { (al=0ffh) OR (ah=al) }
$L000: or al,al ;2
; { (ah=al=0, ZF=1, CY=0) or (ZF=0, CY=0) }
jz $L004 ;7,noj=3
; jump if end of string
; i.e. { ah=al=0, ZF=1, CY=0 }
lodsb ; get byte from p2
mov ah,es:[bx] ; get byte from p1
inc bx
cmp ah,al ; "premature compare" (cmp p1,p2)
jz $L000 ;7,noj=3
; jump if they are already equal
; convert char from p2
sub al,'A' ;3; shift the alfabet 'A' -> 0
cmp al,26 ;3; compare with alphabet size
sbb cl,cl ;2; if ('A'..'Z') then cl=0ffh else 0
and cl,20h ;3; prepare 20h or 0h
add al,cl ;2; convert to shifted lowercase
add al,'A' ;3; shift back
;16 total for conversion
xchg ah,al ; now the one from p1
sub al,41h
cmp al,1Ah
sbb cl,cl
and cl,20h
add al,cl
add al,41h
cmp al,ah ; now compare after conversion (cmp p1,p2)
jz $L000 ;7,noj=3
; jump if match after conversion
; { al= *p1, ah=*p2, ZF=0, CY=*p1-*p2 }
sbb al,al ; a: (CY) -> (0FFh and CY)
; b: (NC) -> (0 and NC)
sbb al,0FFh ; a: al := 0FFh
; b: al := 1
cbw ; a: ax := 0FFFFh (-1)
; b: ax := 1
$L004: mov si,dx
pop ds
pop bp
ret
_dev_stricmp ENDP
PAGE
;
; The two stage alternative
; lds si,[p1] ; Get ptr p1
; les bx,[p2] ; get ptr p2
; mov cx,0FFFFh
; xor ax,ax ; prepare search for '\0'
; repne scasb ; search
; not cx ; cx := # nonzero + 1
; sub bx,cx ; restore p2
;; Now the real compare
;; Watch it: because cx >= 1 we do not have to test
;; for cx==0 the first time! (repe cmpsb would do it)
;$L000 lodsb ; get *p1
; mov ah,es:[bx] ; get *p2
; inc bx
; cmp al,ah ; "premature" cmp *p1,*p2
; jz $L003 ;7,noj=3
; ; jump if already equal
;
; convert al and ah
;
; cmp al,ah ; cmp *p1,*p2 after conversion
;$L003 loope $L000 ;8,noj=4
; ; jump if same and length not exhausted
;; $L000..$L003 is the equivalent of: repe cmpsb (but case insensitive)
;
; jz $L004 ; jump if cx times done
; sbb al,al ; a: (CY) -> (0FFh and CY)
; ; b: (NC) -> (0 and NC)
; sbb al,0FFh ; a: al := 0FFh
; ; b: al := 1
; cbw ; a: ax := 0FFFFh (-1)
; ; b: ax := 1
;$L004 mov si,dx
_TEXT ENDS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -