home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / platform / strncat.asm < prev    next >
Assembly Source File  |  1998-06-17  |  7KB  |  253 lines

  1.         page    ,132
  2.         title   strncat - append n chars of string1 to string2
  3. ;***
  4. ;strncat.asm - append n chars of string to new string
  5. ;
  6. ;       Copyright (c) 1985-1997, Microsoft Corporation. All rights reserved.
  7. ;
  8. ;Purpose:
  9. ;       defines strncat() - appends n characters of string onto
  10. ;       end of other string
  11. ;
  12. ;*******************************************************************************
  13.  
  14.         .xlist
  15.         include cruntime.inc
  16.         .list
  17.  
  18. page
  19. ;***
  20. ;char *strncat(front, back, count) - append count chars of back onto front
  21. ;
  22. ;Purpose:
  23. ;       Appends at most count characters of the string back onto the
  24. ;       end of front, and ALWAYS terminates with a null character.
  25. ;       If count is greater than the length of back, the length of back
  26. ;       is used instead.  (Unlike strncpy, this routine does not pad out
  27. ;       to count characters).
  28. ;
  29. ;       Algorithm:
  30. ;       char *
  31. ;       strncat (front, back, count)
  32. ;           char *front, *back;
  33. ;           unsigned count;
  34. ;       {
  35. ;           char *start = front;
  36. ;
  37. ;           while (*front++)
  38. ;               ;
  39. ;           front--;
  40. ;           while (count--)
  41. ;               if (!(*front++ = *back++))
  42. ;                   return(start);
  43. ;           *front = '\0';
  44. ;           return(start);
  45. ;       }
  46. ;
  47. ;Entry:
  48. ;       char *   front - string to append onto
  49. ;       char *   back  - string to append
  50. ;       unsigned count - count of max characters to append
  51. ;
  52. ;Exit:
  53. ;       returns a pointer to string appended onto (front).
  54. ;
  55. ;Uses:  ECX, EDX
  56. ;
  57. ;Exceptions:
  58. ;
  59. ;*******************************************************************************
  60.  
  61.     CODESEG
  62.  
  63.     public  strncat
  64. strncat proc
  65. ;   front:ptr byte,
  66. ;   back:ptr byte,
  67. ;   count:IWORD
  68.  
  69.         .FPO    ( 0, 3, 0, 0, 0, 0 )
  70.  
  71.         mov     ecx,[esp + 0ch]     ; ecx = count
  72.         push    edi                 ; preserve edi
  73.         test    ecx,ecx
  74.         jz      finish              ; leave if count is zero
  75.  
  76.         mov     edi,[esp + 8]       ; edi -> front string
  77.         push    esi                 ; preserve esi
  78.         test    edi,3               ; is string aligned on dword (4 bytes)
  79.         push    ebx                 ; preserve ebx
  80.         je      short find_end_of_front_string_loop
  81.  
  82.         ; simple byte loop until string is aligned
  83.  
  84. front_misaligned:
  85.         mov     al,byte ptr [edi]
  86.         inc     edi
  87.         test    al,al
  88.         je      short start_byte_3
  89.         test    edi,3
  90.         jne     short front_misaligned
  91.  
  92. find_end_of_front_string_loop:
  93.         mov     eax,dword ptr [edi] ; read dword (4 bytes)
  94.         mov     edx,7efefeffh
  95.         add     edx,eax
  96.         xor     eax,-1
  97.         xor     eax,edx
  98.         add     edi,4
  99.         test    eax,81010100h
  100.         je      short find_end_of_front_string_loop
  101.  
  102. ; found zero byte in the loop
  103.         mov     eax,[edi - 4]
  104.         test    al,al               ; is it byte 0
  105.         je      short start_byte_0
  106.         test    ah,ah               ; is it byte 1
  107.         je      short start_byte_1
  108.         test    eax,00ff0000h       ; is it byte 2
  109.         je      short start_byte_2
  110.         test    eax,0ff000000h      ; is it byte 3
  111.         jne     short find_end_of_front_string_loop
  112.                                     ; taken if bits 24-30 are clear and bit
  113.                                     ; 31 is set
  114. start_byte_3:
  115.         dec     edi
  116.         jmp     short copy_start
  117. start_byte_2:
  118.         sub     edi,2
  119.         jmp     short copy_start
  120. start_byte_1:
  121.         sub     edi,3
  122.         jmp     short copy_start
  123. start_byte_0:
  124.         sub     edi,4
  125.  
  126. ; edi now points to the end of front string.
  127.  
  128. copy_start:
  129.         mov     esi,[esp + 14h]     ; esi -> back string
  130.         test    esi,3               ; is back string is dword aligned?
  131.         jnz     back_misaligned
  132.  
  133.         mov     ebx,ecx             ; store count for tail loop
  134.  
  135.         shr     ecx,2
  136.         jnz     short main_loop_entrance
  137.         jmp     short tail_loop_start   ; 0 < counter < 4
  138.  
  139. ; simple byte loop until back string is aligned
  140.  
  141. back_misaligned:
  142.         mov     dl,byte ptr [esi]
  143.         inc     esi
  144.         test    dl,dl
  145.         je      short byte_0
  146.         mov     [edi],dl
  147.         inc     edi
  148.         dec     ecx
  149.         jz      empty_counter
  150.         test    esi,3
  151.         jne     short back_misaligned
  152.         mov     ebx,ecx             ; store count for tail loop
  153.         shr     ecx,2               ; convert ecx to dword count
  154.         jnz     short main_loop_entrance
  155.  
  156. tail_loop_start:
  157.         mov     ecx,ebx
  158.         and     ecx,3               ; ecx = count of leftover bytes after the
  159.                                     ; dwords have been concatenated
  160.         jz      empty_counter
  161.  
  162. tail_loop:
  163.         mov     dl,byte ptr [esi]
  164.         inc     esi
  165.         mov     [edi],dl
  166.         inc     edi
  167.         test    dl,dl
  168.         je      short finish1       ; '\0' was already copied
  169.         dec     ecx
  170.         jnz     tail_loop
  171.  
  172. empty_counter:
  173.         mov     [edi],cl            ; cl=0;
  174. finish1:
  175.         pop     ebx
  176.         pop     esi
  177. finish:
  178.         mov     eax,[esp + 8]       ; return in eax pointer to front string
  179.         pop     edi
  180.         ret                         ; _cdecl return
  181.  
  182.  
  183. byte_0:
  184.         mov     [edi],dl
  185.         mov     eax,[esp + 10h]     ; return in eax pointer to front string
  186.         pop     ebx
  187.         pop     esi
  188.         pop     edi
  189.         ret                         ; _cdecl return
  190.  
  191.  
  192. main_loop:                          ; edx contains first dword of back string
  193.         mov     [edi],edx           ; store one more dword
  194.         add     edi,4               ; kick pointer to front string
  195.  
  196.         dec     ecx
  197.         jz      tail_loop_start
  198. main_loop_entrance:
  199.         mov     edx,7efefeffh
  200.         mov     eax,dword ptr [esi] ; read 4 bytes
  201.  
  202.         add     edx,eax
  203.         xor     eax,-1
  204.  
  205.         xor     eax,edx
  206.         mov     edx,[esi]           ; it's in cache now
  207.  
  208.         add     esi,4               ; kick pointer to back string
  209.         test    eax,81010100h
  210.  
  211.         je      short main_loop
  212.  
  213. ; may be found zero byte in the loop
  214.         test    dl,dl               ; is it byte 0
  215.         je      short byte_0
  216.         test    dh,dh               ; is it byte 1
  217.         je      short byte_1
  218.         test    edx,00ff0000h       ; is it byte 2
  219.         je      short byte_2
  220.         test    edx,0ff000000h      ; is it byte 3
  221.         jne short main_loop         ; taken if bits 24-30 are clear and bit
  222.                                     ; 31 is set
  223. byte_3:
  224.         mov     [edi],edx
  225.         mov     eax,[esp + 10h]     ; return in eax pointer to front string
  226.         pop     ebx
  227.         pop     esi
  228.         pop     edi
  229.         ret                         ; _cdecl return
  230.  
  231. byte_2:
  232.         mov     [edi],dx
  233.         xor     edx,edx
  234.         mov     eax,[esp + 10h]     ; return in eax pointer to front string
  235.         mov     [edi + 2],dl
  236.         pop     ebx
  237.         pop     esi
  238.         pop     edi
  239.         ret                         ; _cdecl return
  240.  
  241. byte_1:
  242.         mov     [edi],dx
  243.         mov     eax,[esp + 10h]     ; return in eax pointer to front string
  244.         pop     ebx
  245.         pop     esi
  246.         pop     edi
  247.         ret                         ; _cdecl return
  248.  
  249. strncat endp
  250.  
  251.         end
  252.  
  253.