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