Leaked source code of windows server 2003
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.

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