
 ; ------------------------------------------------------------------
 ;
 ; Function InChrR(sStr As String, ByVal AscW_Chr As Integer, _
 ;                 Optional ByVal lStartPos As Long = 0, _
 ;                 Optional ByVal lLeftLimit As Long = 1) As Long
 ;
 ; InChrR searches for a character in another string starting at the
 ; end of the string and if it is found returns the position of the
 ; first match from the string end as the function result.
 ;
 ; It uses a one based character index (1st character is 1, 2nd is 2 etc)
 ; for both the lStartPos parameter and the returned character position.
 ;
 ; If the optional start position parameter is omitted/less than one
 ; it defaults to starting the search at the end of the string. This
 ; parameter specifies a position offset from the start of the data.
 ;
 ; The optional left limit parameter specifies the one based position in
 ; the string for the left-most possible search pattern match. If omitted
 ; or less than one the string is searched from start position to base.
 ; ------------------------------------------------------------------
 ; If the function succeeds, it returns the one based index
 ; of the first character match from the end, or:
 ;  0 = no match found
 ;  0 = zero length main string
 ;  0 = startpos parameter out of range (startpos > len str)
 ;  0 = leftlimit out of range (leftlimit > startpos)
 ; ------------------------------------------------------------------

 .686             ; 32-bit instruction set
 .model flat      ; Protected memory, 4GB limit
 .code            ; Start of code

InChrR proc near  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

   push ebp          ; preserve base pointer value
   mov ebp, esp      ; set up pointer to parameters

   string equ [ebp+12]
   find   equ [ebp+16]
   start  equ [ebp+20] ; friendly param names
   limit  equ [ebp+24]
   return equ [ebp+28]

   push esi          ; preserve registers
   push ebx

   mov esi, string   ; copy str descriptor
   mov edx, start    ; copy start pos param
   mov esi,[esi]     ; extract str pointer
   xor eax, eax      ; zero default return
   test esi,esi      ; validate str pointer
   jz _exitp         ; exit null str pointer

   mov ebx, limit    ; copy left limit param
   mov ecx,[esi-4]   ; extract str byte length

   dec ebx           ; convert param to zero base
   cmovs ebx,eax     ; default to zero based lbound
   shr ecx, 1        ; convert byte length to chars
   jz _exitp         ; exit empty string passed

   test edx,edx      ; validate optional start param
   jg _validate      ; start greater than zero (jnsz)
   mov edx, ecx      ; default to last possible pos
   jmp _start

  _validate:
   cmp ecx, edx      ; is start pos within str len
   jb _exitp         ; hit cannot occur > length

  _start:
   mov cx, find      ; prep cx for wchar search

  _chr:              ; walk up str unicode chars
   dec edx           ; offset index to prev wchar
   cmp edx, ebx      ; test bottom of search scope
   jl _exitp         ; reached search scope limit
   cmp cx,[esi+edx*2]; compare next char with find
   jne _chr          ; continue search for find char

   mov eax, edx      ; assign result hit position
   inc eax           ; convert result to one base

  _exitp:
   mov ecx, return   ; get address of return value
   mov [ecx],eax     ; store the function result

   pop ebx           ; restore registers
   pop esi
   pop ebp           ; restore base pointer register

   xor eax, eax      ; clear eax to tell VB all is okay
   ret 24            ; cleanup (lpO, p1, p2, p3, p4, rc)

 ; ------------------------------------------------------------------

InChrR endp     ; end of procedure
end InChrR      ; end of code, indicate entry point

 ; ------------------------------------------------------------------
