home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk12 / cpgrep / cpgrepsb.asm < prev    next >
Encoding:
Assembly Source File  |  1989-11-20  |  14.9 KB  |  679 lines

  1. ; Created by Microsoft Corp. 1986
  2. name cpgrepsub
  3.  
  4. retlen    equ    2            ; Size of return address on stack
  5.  
  6. dgroup    group    _data
  7.  
  8. extrn    _casesen:    word        ; Case-sensitivity flag
  9. extrn    _stringlist:    word        ; Table of string lists
  10. extrn    _target:    byte        ; Target string
  11. extrn    _targetlen:    word        ; Length of target string
  12. extrn    _transtab:    byte        ; Translation table for _findlist
  13.  
  14. ;    This segment is puposely word-aligned.  See note
  15. ;    in _findlist below.
  16.  
  17. _text    segment word public 'code'
  18.     assume    cs:_text, ds:dgroup, es:nothing, ss:dgroup
  19.  
  20. ; char            *findone(buffer,bufend)
  21. ; char            *buffer        /* Buffer in which to search */
  22. ; char            *bufend;    /* End of buffer */
  23. ;
  24. ; NOTE: targetlen MUST BE greater than zero
  25.  
  26. buffer    equ    word ptr [bp+retlen+2]
  27. bufend    equ    word ptr [bp+retlen+4]
  28.  
  29.     EVEN
  30.  
  31.     public    _findone
  32. _findone proc    near
  33.     push    bp
  34.     mov    bp,sp
  35.     push    di
  36.     push    si
  37.     push    es
  38.     push    ds            ; ES = DS
  39.     pop    es
  40.     mov    cx,bufend        ; CX = end of buffer
  41.     mov    di,buffer        ; ES:DI = buffer
  42.     sub    cx,di            ; CX = length of buffer
  43.     jbe    sfnomatch        ;  length less than or equal to zero
  44.     mov    dx,_targetlen        ; DX = length of target
  45.     dec    dx            ; Decrement it
  46.     sub    cx,dx            ; target must fit in buffer
  47.     jbe    sfnomatch        ;  (no match if buffer too short)
  48.  
  49. ;    CX = buffer length
  50. ;    DX = target length (minus first character)
  51. ;    ES:DI = buffer pointer
  52.  
  53. sf0:    jcxz    sfnomatch        ; No match if count zero
  54.     mov    si,offset dgroup:_target ; DS:SI = target
  55.     lodsb                ; AL = first byte of target
  56.     repne scasb            ; Look for first character
  57.     jne    sfnomatch        ;  jump if not found
  58.     mov    bx,cx            ; BX = buffer length
  59.     mov    ax,di            ; AX = buffer pointer
  60.     mov    cx,dx            ; Get count for cmpsb
  61.     or    cx,cx            ; Zero? (JCXZ doesn't set flag)
  62.     je    sf1            ;  yes, skip compare
  63.     repe cmpsb            ; Do string compare
  64. sf1:    mov    di,ax            ; DI = buffer pointer
  65.     mov    cx,bx            ; CX = buffer length
  66.     jne    sf0            ; Loop if no match
  67.     dec    ax            ; AX = offset of start of match
  68.     jmp    short sf4
  69.  
  70. sfnomatch:
  71.     xor    ax,ax            ; No match
  72. sf4:    pop    es
  73.     pop    si
  74.     pop    di
  75.     pop    bp
  76.     ret
  77. _findone endp
  78.  
  79.  
  80. ; int            revfind(s,c,slen)
  81. ; char            *s;        /* String to search */
  82. ; int            c;        /* Char to search for */
  83. ; int            slen;        /* Length of s */
  84.  
  85. s    equ    [bp+retlen+2]
  86. c    equ    [bp+retlen+4]
  87. slen    equ    [bp+retlen+6]
  88.  
  89.     EVEN
  90.  
  91.     public    _revfind
  92. _revfind proc    near
  93.     push    bp
  94.     mov    bp,sp
  95.     push    di
  96.     push    es
  97.     push    ds
  98.     pop    es
  99.     mov    di,s
  100.     mov    ax,c
  101.     mov    cx,slen
  102.     jcxz    rf1
  103.     std
  104.     repne scasb
  105.     cld
  106.     mov    cx,s
  107.     jne    rf0
  108.     inc    di
  109. rf0:    sub    cx,di
  110. rf1:    mov    ax,cx
  111.     pop    es
  112.     pop    di
  113.     pop    bp
  114.     ret
  115. _revfind endp
  116.  
  117.  
  118. ; int            countlines(start,finish)
  119. ; char            *start;
  120. ; char            *finish;
  121.  
  122. start    equ    [bp+retlen+2]
  123. finish    equ    [bp+retlen+4]
  124.  
  125.     EVEN
  126.  
  127.     public    _countlines
  128. _countlines proc near
  129.     push    bp
  130.     mov    bp,sp
  131.     push    di
  132.     push    es
  133.     push    ds
  134.     pop    es
  135.     xor    dx,dx            ; Accumulate count in DX
  136.     mov    di,start        ; ES:DI points to start
  137.     mov    cx,finish        ; Put length in CX
  138.     sub    cx,di
  139.     jbe    cl1            ;  branch if no bytes
  140.     mov    al,0Ah            ; Search for linefeeds
  141. cl0:    jcxz    cl1            ; Exit loop if count zero
  142.     repne scasb            ; Do search
  143.     jne    cl1            ;  branch if none found
  144.     inc    dx            ; Increment count
  145.     jmp    short cl0        ; Loop
  146. cl1:    mov    ax,dx            ; Return line count in AX
  147.     pop    es
  148.     pop    di
  149.     pop    bp
  150.     ret
  151. _countlines endp
  152.  
  153.  
  154. ; char            *findlist(buffer,bufend)
  155. ; char            *buffer;    /* Buffer to search */
  156. ; char            *bufend;    /* End of buffer */
  157.  
  158. savesi    equ    word ptr [bp-2]
  159. endbyte    equ    byte ptr [bp-4]
  160.  
  161. stringnode struc
  162.     s_alt    dw    ?        ; List of alternate portions
  163.     s_suf    dw    ?        ; Pointer to suffix string list
  164.     s_must    dw    ?        ; Length of portion that must match
  165. stringnode ends
  166.  
  167.     EVEN
  168.  
  169. flworker dw    findsubi, findsub    ; Worker dispatch table
  170.  
  171.     public    _findlist
  172. _findlist proc    near
  173.     ASSUME    DS:DGROUP, ES:NOTHING, SS:DGROUP
  174.  
  175.     push    bp
  176.     mov    bp,sp
  177.     sub    sp,4            ; Make room for local vars
  178.     push    di
  179.     push    si
  180.     push    ds
  181.     pop    es
  182.     ASSUME    ES:DGROUP
  183.  
  184. ;    We mark the end of our search buffer with 0FFh so that
  185. ;    any comparisons that might run past the end of the buffer
  186. ;    will fail on the 0FFh.  We choose 0FFh so that if the
  187. ;    comparison fails on it, it will always appear as though
  188. ;    the string in the buffer is greater that the string in
  189. ;    the search list.  This will prevent us from stopping
  190. ;    the search too soon.  Of course, we must restore the byte
  191. ;    when we're done.
  192.  
  193.     mov    bx,bufend        ; BX = end of buffer
  194.     mov    al,0FFh            ; End marker
  195.     xchg    byte ptr [bx],al    ; AL = byte after end of buffer
  196.     mov    endbyte,al        ; Save the byte
  197.  
  198.     mov    cx,bx            ; CX = end of buffer
  199.     mov    si,buffer        ; SI = buffer
  200.     sub    cx,si            ; CX = buffer length
  201.     jbe    fl1            ;  no match if empty buffer
  202.     mov    bx,offset dgroup:_transtab ; BX = translation table address
  203.  
  204.     mov    di,_casesen        ; Get flag
  205.     shl    di,1            ; Scale to word index
  206.     call    cs:flworker[di]        ; Call helper
  207.     jc    fl1            ;  branch if no match
  208.  
  209. ;    We have a match
  210. ;
  211. ;    SI = offset of first character past end of matched string
  212. ;    savesi = offset of first character past start of matched string
  213.  
  214.     mov    ax,savesi        ; AX = 1st char past start
  215.     dec    ax            ; AX = start of matched string
  216.     jmp    short fl2
  217.  
  218. ;    We did not find a match
  219.  
  220. fl1:
  221.     xor    ax,ax            ; Return NULL
  222.  
  223. ;    Restore end byte before leaving
  224.  
  225. fl2:
  226.     mov    bx,bufend        ; BX = end of buffer
  227.     mov    dl,endbyte        ; DL = end byte
  228.     mov    [bx],dl            ; Restore byte
  229.  
  230.     pop    si
  231.     pop    di
  232.     mov    sp,bp
  233.     pop    bp
  234.     ret
  235.  
  236. _findlist endp
  237.  
  238.  
  239. ;***    findsub - case-sensitive worker for _findlist
  240. ;
  241. ;    This function does most of the work for
  242. ;    case-sensitive multi-string searches.
  243. ;
  244. ;    ENTRY    BX = address of translation table
  245. ;        CX = number of bytes left in buffer
  246. ;        DS:SI = buffer pointer
  247. ;        SS:BP = pointer to stack frame for _findlist
  248. ;    EXIT    Carry set
  249. ;            No match
  250. ;        Carry clear
  251. ;            DS:SI = pointer to first character after match
  252. ;    USES    AX, CX, DX, DI, SI, Flags
  253.  
  254.     EVEN
  255.  
  256.     public    findsub, fs0, fs1, fs2, fs3, fs4, fs5, fs6
  257. findsub    proc    near
  258.     ASSUME    DS:DGROUP, ES:DGROUP, SS:DGROUP
  259.  
  260. fs0:
  261.     xor    ax,ax            ; AH = 0
  262.  
  263. ;    AH = 0
  264. ;    BX = address of translation table
  265. ;    CX = number of bytes left in buffer
  266. ;    SI = buffer pointer
  267. ;    DS = ES = SS = DGROUP
  268.  
  269. fs1:
  270.     lodsb                ; Character in AL
  271.     xlat byte ptr [bx]        ; Translate character to index
  272.     or    al,al            ; Zero means invalid 1st byte
  273.     loopz    fs1            ;  if so, try next character
  274.  
  275. ;    Either the zero bit is set, meaning the buffer is empty,
  276. ;    or the zero bit is clear, meaning we have a valid first
  277. ;    character.  Either way, CX has been decremented.
  278.  
  279.     jz    fs6            ;  branch if buffer empty
  280.     mov    savesi,si        ; Save buffer pointer
  281.     shl    ax,1            ; Scale to word index
  282.     mov    di,ax
  283.     mov    di,_stringlist[di]    ; DI points to string record
  284.     or    di,di            ; One byte match? (OR clears carry)
  285.     jz    fs3            ;  yes, skip ahead
  286.  
  287. ;    Loop to search for match.
  288. ;    BX = address of translation table
  289. ;    DI = pointer to string record
  290. ;    SI = pointer into buffer
  291.  
  292. fs2:
  293.     mov    cx,[di].s_must        ; CX = length of string
  294.     sub    di,cx            ; DI = pointer to string
  295.     mov    dx,si            ; Save pointer to start of suffix
  296.     repe cmpsb            ; Strings match?
  297.     ja    fs4            ;  no, try alternate if follows
  298.     jb    fs5            ;  no, cannot be in this list
  299.     add    di,cx            ; DI = pointer to string record
  300.     mov    di,[di].s_suf        ; Get pointer to suffix string list
  301.     or    di,di            ; Is there one? (OR clears carry)
  302.     jnz    fs2            ;  yes, keep looking
  303.  
  304. ;    Match found
  305.  
  306. fs3:
  307.     ret                ;  no, we have a match
  308.  
  309. ;    Try alternate suffix
  310.  
  311. fs4:
  312.     add    di,cx            ; DI = pointer to string record
  313.     mov    di,[di].s_alt        ; Get pointer to alternate
  314.     mov    si,dx            ; Restore SI to start of suffix
  315.     or    di,di            ; Is there one?
  316.     jnz    fs2            ;  yes, loop
  317.  
  318. ;    Try new first character
  319.  
  320. fs5:
  321.     mov    cx,bufend        ; CX = end of buffer
  322.     mov    si,savesi        ; Restore SI to saved value
  323.     sub    cx,si            ; CX = length of buffer
  324.     ja    short fs0        ; Try next character in buffer
  325.  
  326. ;    No match
  327.  
  328. fs6:
  329.     stc                ; No match
  330.     ret
  331.  
  332. findsub    endp
  333.  
  334.  
  335. ;***    findsubi - case-insensitive worker for _findlist
  336. ;
  337. ;    This function does most of the work for
  338. ;    case-insensitive multi-string searches.
  339. ;
  340. ;    ENTRY    BX = address of translation table
  341. ;        CX = number of bytes left in buffer
  342. ;        DS:SI = buffer pointer
  343. ;        SS:BP = pointer to stack frame for _findlist
  344. ;    EXIT    Carry set
  345. ;            No match
  346. ;        Carry clear
  347. ;            DS:SI = pointer to first character after match
  348. ;    USES    AX, CX, DX, DI, SI, Flags
  349.  
  350.     EVEN
  351.  
  352.     public    findsubi
  353. findsubi proc    near
  354.     ASSUME    DS:DGROUP, ES:DGROUP, SS:DGROUP
  355.  
  356. fsi0:
  357.     xor    ax,ax            ; AH = 0
  358.  
  359. ;    AH = 0
  360. ;    BX = address of translation table
  361. ;    CX = number of bytes left in buffer
  362. ;    SI = buffer pointer
  363. ;    DS = ES = SS = DGROUP
  364.  
  365. fsi1:
  366.     lodsb                ; Character in AL
  367.     xlat byte ptr [bx]        ; Translate character to index
  368.     or    al,al            ; Zero means invalid 1st byte
  369.     loopz    fsi1            ;  if so, try next character
  370.  
  371. ;    Either the zero bit is set, meaning the buffer is empty,
  372. ;    or the zero bit is clear, meaning we have a valid first
  373. ;    character.  Either way, CX has been decremented.
  374.  
  375.     jz    fsi7            ;  branch if buffer empty
  376.     mov    savesi,si        ; Save buffer pointer
  377.     shl    ax,1            ; Scale to word index
  378.     mov    di,ax
  379.     mov    di,_stringlist[di]    ; DI points to string record
  380.     or    di,di            ; One byte match? (OR clears carry)
  381.     jz    fsi4            ;  yes, skip ahead
  382.  
  383. ;    Loop to search for match.
  384. ;    BX = address of translation table
  385. ;    DI = pointer to string record
  386. ;    SI = pointer into buffer
  387.  
  388. fsi2:
  389.     mov    cx,[di].s_must        ; CX = length of string
  390.     sub    di,cx            ; DI = pointer to string
  391.     mov    dx,si            ; Save pointer to start of suffix
  392. fsi3:    lodsb                ; Byte in AL, SI = SI + 1
  393.     mov    ah,[di]            ; Byte in AH, DI = DI + 1
  394.     inc    di
  395.     or    ax,2020h        ; Fold bytes onto lower case
  396.     cmp    al,ah            ; Compare bytes
  397.     loope    fsi3            ; Loop while same
  398.     ja    fsi5            ;  no, try alternate if follows
  399.     jb    fsi6            ;  no, cannot be in this list
  400.     add    di,cx            ; DI = pointer to string record
  401.     mov    di,[di].s_suf        ; Get pointer to suffix string list
  402.     or    di,di            ; Is there one? (OR clears carry)
  403.     jnz    fsi2            ;  yes, keep looking
  404.  
  405. ;    Match found
  406.  
  407. fsi4:
  408.     ret                ;  no, we have a match
  409.  
  410. ;    Try alternate suffix
  411.  
  412. fsi5:
  413.     add    di,cx            ; DI = pointer to string record
  414.     mov    di,[di].s_alt        ; Get pointer to alternate
  415.     mov    si,dx            ; Restore SI to start of suffix
  416.     or    di,di            ; Is there one?
  417.     jnz    fsi2            ;  yes, loop
  418.  
  419. ;    Try new first character
  420.  
  421. fsi6:
  422.     mov    cx,bufend        ; CX = end of buffer
  423.     mov    si,savesi        ; Restore SI to saved value
  424.     sub    cx,si            ; CX = length of buffer
  425.     ja    short fsi0        ; Try next character in buffer
  426.  
  427. ;    No match
  428.  
  429. fsi7:
  430.     stc                ; No match
  431.     ret
  432.  
  433. findsubi endp
  434.  
  435.  
  436. ; int            strnspn(s,t,n)
  437. ; char            *s;        /* String to search */
  438. ; char            *t;        /* Target list */
  439. ; int            n;        /* Length of s */
  440.  
  441. s    equ    word ptr [bp+retlen+2]
  442. t    equ    word ptr [bp+retlen+4]
  443. n    equ    word ptr [bp+retlen+6]
  444.  
  445.     EVEN
  446.  
  447.     public    _strnspn
  448. _strnspn proc    near
  449.     push    bp
  450.     mov    bp,sp
  451.     push    di
  452.     push    si
  453.     push    ds
  454.     pop    es
  455.     cld
  456.     mov    bx,t            ; BX = t
  457.     mov    di,bx            ; DI = t
  458.     xor    al,al            ; Search for 0 byte
  459.     mov    cx,0FFFFh
  460.     repne scasb
  461.     dec    di            ; Back up to 0
  462.     sub    di,bx            ; DI = length of t
  463.     jz    spn1            ; Done if length of t is 0
  464.     mov    dx,di            ; DX = length of t
  465.     mov    si,s            ; SI = s
  466.     mov    cx,n            ; CX = length of s
  467.     jcxz    spn1            ; Check for null string
  468.     push    bp
  469. spn0:    lodsb                ; AL = next char in s
  470.     mov    bp,cx            ; BP = length of s
  471.     mov    cx,dx            ; CX = length of t
  472.     mov    di,bx            ; DI = t
  473.     repne scasb            ; Scan until match found
  474.     mov    cx,bp            ; CX = length of s
  475.     loope    spn0            ; Loop if match found
  476.     pop    bp
  477.     je    spn1            ; Skip ahead if end of s reached
  478.     dec    si            ; Back up one char
  479. spn1:    sub    si,s            ; SI = length of prefix
  480.     mov    ax,si            ; AX = length of prefix
  481.     pop    si
  482.     pop    di
  483.     pop    bp
  484.     ret
  485. _strnspn endp
  486.  
  487.  
  488. ; int            strncspn(s,t,n)
  489. ; char            *s;        /* String to search */
  490. ; char            *t;        /* Target list */
  491. ; int            n;        /* Length of s */
  492.  
  493.     EVEN
  494.  
  495.     public    _strncspn
  496. _strncspn proc    near
  497.     push    bp
  498.     mov    bp,sp
  499.     push    di
  500.     push    si
  501.     push    ds
  502.     pop    es
  503.     cld
  504.     mov    bx,t            ; BX = t
  505.     mov    di,bx            ; DI = t
  506.     xor    al,al            ; Search for 0 byte
  507.     mov    cx,0FFFFh
  508.     repne scasb
  509.     dec    di            ; Back up to 0
  510.     sub    di,bx            ; DI = length of t
  511.     mov    ax,n            ; Assume length of t is 0
  512.     jz    cspn2            ; Done if length of t is 0
  513.     mov    dx,di            ; DX = length of t
  514.     mov    si,s            ; SI = s
  515.     mov    cx,ax            ; CX = length of s
  516.     jcxz    cspn1            ; Check for null string
  517.     push    bp
  518. cspn0:    lodsb                ; AL = next char in s
  519.     mov    bp,cx            ; BP = length of s
  520.     mov    cx,dx            ; CX = length of t
  521.     mov    di,bx            ; DI = t
  522.     repne scasb            ; Scan until match found
  523.     mov    cx,bp            ; CX = length of s
  524.     loopne    cspn0            ; Loop if match not found
  525.     pop    bp
  526.     jne    cspn1            ; Skip ahead if end of s reached
  527.     dec    si            ; Back up one char
  528. cspn1:    sub    si,s            ; SI = length of prefix
  529.     mov    ax,si            ; AX = length of prefix
  530. cspn2:    pop    si
  531.     pop    di
  532.     pop    bp
  533.     ret
  534. _strncspn endp
  535.  
  536.  
  537. ;    cmpsen - case-sensitive comparison
  538. ;
  539. ;    ENTRY    DS:SI = buffer
  540. ;        ES:DI = string
  541. ;        CX = length of string
  542. ;    EXIT    CX = length of string unused
  543. ;        DI = unused portion of string
  544. ;        Z set
  545. ;            match found
  546. ;        Z clear
  547. ;            no match
  548. ;    USES    CX, DI, SI, Flags
  549.  
  550.     EVEN
  551.  
  552. cmpsen    proc    near
  553.     repe cmpsb
  554.     ret
  555. cmpsen    endp
  556.  
  557.  
  558. ;    cmpinsen - case-insensitive comparison
  559. ;
  560. ;    ENTRY    DS:SI = buffer
  561. ;        ES:DI = string
  562. ;        CX = length of string
  563. ;    EXIT    CX = length of string unused
  564. ;        DI = unused portion of string
  565. ;        Z set
  566. ;            match found
  567. ;        Z clear
  568. ;            no match
  569. ;    USES    AX, CX, DI, SI, Flags
  570.  
  571.     EVEN
  572.  
  573. cmpinsen proc    near
  574. cmpi0:    lodsb                ; Byte in AL, SI = SI + 1
  575.     mov    ah,[di]            ; Byte in AH, DI = DI + 1
  576.     inc    di
  577.     or    ax,2020h        ; Fold bytes onto lower case
  578.     cmp    al,ah            ; Compare bytes
  579.     loope    cmpi0            ; Loop while same
  580.     ret
  581. cmpinsen endp
  582.  
  583.  
  584. ; void            matchstrings(s1,s2,len,nmatched,leg)
  585. ; char            *s1;        /* First string */
  586. ; char            *s2;        /* Second string */
  587. ; int            len;        /* Length */
  588. ; int            *nmatched;    /* Number of bytes matched */
  589. ; int            *leg;        /* Less than, equal, greater than */
  590.  
  591. cm_s1        equ    word ptr [bp+retlen+2]
  592. cm_s2        equ    word ptr [bp+retlen+4]
  593. cm_len        equ    word ptr [bp+retlen+6]
  594. cm_nmatched    equ    word ptr [bp+retlen+8]
  595. cm_leg        equ    word ptr [bp+retlen+10]
  596.  
  597.     EVEN
  598.  
  599.     public    _matchstrings
  600. _matchstrings proc near
  601.     ASSUME    DS:DGROUP, ES:NOTHING, SS:DGROUP
  602.  
  603.     push    bp
  604.     mov    bp,sp
  605.     push    di
  606.     push    si
  607.     push    ds
  608.     pop    es
  609.     ASSUME    ES:DGROUP
  610.     mov    di,cm_s2
  611.     mov    si,cm_s1
  612.     mov    cx,cm_len
  613.     cmp    _casesen,0
  614.     je    cm0
  615.     call    cmpsen
  616.     jmp    short cm1
  617. cm0:    call    cmpinsen
  618. cm1:    mov    bx,cm_leg
  619.     mov    word ptr [bx],0        ; Assume equal
  620.     jz    cm2            ;  yes, skip ahead
  621.     mov    word ptr [bx],1        ; Assume greater than
  622.     jg    cm1a            ;  yes, skip ahead
  623.     mov    word ptr [bx],-1    ; Less than
  624. cm1a:    dec    si
  625. cm2:    sub    si,cm_s1
  626.     mov    bx,cm_nmatched
  627.     mov    [bx],si
  628.     pop    si
  629.     pop    di
  630.     pop    bp
  631.     ret
  632.  
  633. _matchstrings endp
  634.  
  635.  
  636. ; int            strcmp(s1,s2)
  637. ; char            *s1;        /* First string */
  638. ; char            *s2;        /* Second string */
  639.  
  640.     public    _strcmp
  641. _strcmp    proc    near
  642.     push    bp
  643.     mov    bp,sp
  644.     push    di
  645.     push    si
  646.     push    ds
  647.     pop    es
  648.     mov    si,[bp+4]        ; DS:SI = s1
  649.     mov    di,[bp+6]        ; ES:DI = s2
  650. sc0:    lodsb                ; AL = *s1++
  651.     scasb                ; AL - *s2++
  652.     jne    sc1            ;  branch if no match
  653.     or    al,al            ; End of s1?
  654.     jne    sc0            ;  no, loop
  655.     cbw                ; AX = 0
  656.     jmp    short sc2        ; Exit
  657. sc1:    mov    ax,1            ; Assume s1 > s2
  658.     jg    sc2            ;  yes, branch
  659.     neg    ax            ; s1 < s2
  660. sc2:    pop    si
  661.     pop    di
  662.     pop    bp
  663.     ret
  664. _strcmp    endp
  665.  
  666.  
  667.     public    _bpt
  668. _bpt    proc    near
  669.     int    3
  670.     ret
  671. _bpt    endp
  672.  
  673. _text    ends
  674.  
  675. _data    segment word public 'data'
  676. _data    ends
  677.  
  678. end
  679.