Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

264 lines
7.7 KiB

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