From: zfysz@nospicedham.fysnet.net   
      
   Hi guys,   
      
   Along with the other stricmp() thread, where as the task is to   
   make it fast, how about I change it slightly for something I   
   am working on.   
      
   I need a small stricmp() in a real mode boot loader.   
      
   See the code at the end of this post for what I have so far.   
   Requirements:   
    16-bit real mode (32-bit instructions okay)   
    Intel x86 assembly (obviously)   
    ds:si->string0 (is asciiz and *not* guaranteed to be uppercase)   
    es:di->string1 (is asciiz and *not* guaranteed to be uppercase)   
    cx = length of string1 (not counting null terminator)   
    return:   
    al -1 if string0 < string1 (or) string0[cx] != '\0'   
    al 0 if string0 = string1   
    al 1 if string0 > string1   
      
      
   One thing I thought of is to change the uppercase() to simply   
   set/clear bit 5 in the char before the compare. For example:   
      
    A = 01000001b   
    a = 01100001b   
      
   I could simply do an   
      
    or al,00100000b   
   or   
    and al,~00100000b   
      
   instead of   
      
    call uppercase   
      
   and this would save the size of the two call instructions   
   as well as the uppercase() procedure, minus the size of two   
   new 'or/and' instructions.   
      
   (even better:   
    and ax,~0010000000100000b   
    now that the two chars are in ah and al)   
      
   However, is this guaranteed to work? Will setting bit 5 falsely   
   change a char from a non-alpha character to an alpha character.   
   No I don't think so. This should work...   
      
      
      
      
      
   In my boot code, I only care if it is equal or not, so no need   
   for the double compare (two jcc's). However, I would like to keep   
   this routine somewhat standard so that I can call it from other   
   code without any assumptions.   
      
      
      
   Anyway, what do you guys think? I can shrink an x86 listing   
   for size but I don't have much knowledge on x86 speed, hence   
   I have not commented on the other stricmp() thread. :-)   
      
   Thanks,   
   Ben   
      
      
   =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-   
   this routine compares (case insensitive) two strings   
   ds:si->string0 (asciiz)   
   es:di->string1   
   cx = length of string1   
   returns al -1 if string0 < string1 (or) string0[cx] != '\0'   
   al 0 if string0 = string1   
   al 1 if string0 > string1   
   stricmp proc near uses si di   
      
   stricmp_loop:   
    mov al,es:[di]   
    inc di   
    call uppercase   
    mov ah,al   
      
    lodsb   
    call uppercase   
      
    cmp al,ah   
    jb short stricmp_less   
    ja short stricmp_above   
    loop stricmp_loop   
      
    ; make sure ds:si-> is an asciiz string at this length   
    xor al,al   
    cmp [si],al   
    jne short stricmp_less   
      
    ret   
      
   stricmp_less:   
    mov al,-1   
    ret   
      
   stricmp_above:   
    mov al,1   
    ret   
      
   stricmp endp   
      
   =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-   
   upper case the letter in al returning it in al   
   uppercase proc near   
    cmp al,'a'   
    jb short uppercase_done   
    cmp al,'z'   
    ja short uppercase_done   
    sub al,32   
   uppercase_done:   
    ret   
   uppercase endp   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|