xref: /reactos/sdk/lib/ucrt/string/i386/strcat.asm (revision 04e0dc4a)
1*04e0dc4aSTimo Kreuzer        page    ,132
2*04e0dc4aSTimo Kreuzer        title   strcat - concatenate (append) one string to another
3*04e0dc4aSTimo Kreuzer;***
4*04e0dc4aSTimo Kreuzer;strcat.asm - contains strcat() and strcpy() routines
5*04e0dc4aSTimo Kreuzer;
6*04e0dc4aSTimo Kreuzer;       Copyright (c) Microsoft Corporation. All rights reserved.
7*04e0dc4aSTimo Kreuzer;
8*04e0dc4aSTimo Kreuzer;Purpose:
9*04e0dc4aSTimo Kreuzer;       STRCAT concatenates (appends) a copy of the source string to the
10*04e0dc4aSTimo Kreuzer;       end of the destination string, returning the destination string.
11*04e0dc4aSTimo Kreuzer;
12*04e0dc4aSTimo Kreuzer;*******************************************************************************
13*04e0dc4aSTimo Kreuzer
14*04e0dc4aSTimo Kreuzer        .xlist
15*04e0dc4aSTimo Kreuzer        include cruntime.inc
16*04e0dc4aSTimo Kreuzer        .list
17*04e0dc4aSTimo Kreuzer
18*04e0dc4aSTimo Kreuzer
19*04e0dc4aSTimo Kreuzerpage
20*04e0dc4aSTimo Kreuzer;***
21*04e0dc4aSTimo Kreuzer;char *strcat(dst, src) - concatenate (append) one string to another
22*04e0dc4aSTimo Kreuzer;
23*04e0dc4aSTimo Kreuzer;Purpose:
24*04e0dc4aSTimo Kreuzer;       Concatenates src onto the end of dest.  Assumes enough
25*04e0dc4aSTimo Kreuzer;       space in dest.
26*04e0dc4aSTimo Kreuzer;
27*04e0dc4aSTimo Kreuzer;       Algorithm:
28*04e0dc4aSTimo Kreuzer;       char * strcat (char * dst, char * src)
29*04e0dc4aSTimo Kreuzer;       {
30*04e0dc4aSTimo Kreuzer;           char * cp = dst;
31*04e0dc4aSTimo Kreuzer;
32*04e0dc4aSTimo Kreuzer;           while( *cp )
33*04e0dc4aSTimo Kreuzer;                   ++cp;           /* Find end of dst */
34*04e0dc4aSTimo Kreuzer;           while( *cp++ = *src++ )
35*04e0dc4aSTimo Kreuzer;                   ;               /* Copy src to end of dst */
36*04e0dc4aSTimo Kreuzer;           return( dst );
37*04e0dc4aSTimo Kreuzer;       }
38*04e0dc4aSTimo Kreuzer;
39*04e0dc4aSTimo Kreuzer;Entry:
40*04e0dc4aSTimo Kreuzer;       char *dst - string to which "src" is to be appended
41*04e0dc4aSTimo Kreuzer;       const char *src - string to be appended to the end of "dst"
42*04e0dc4aSTimo Kreuzer;
43*04e0dc4aSTimo Kreuzer;Exit:
44*04e0dc4aSTimo Kreuzer;       The address of "dst" in EAX
45*04e0dc4aSTimo Kreuzer;
46*04e0dc4aSTimo Kreuzer;Uses:
47*04e0dc4aSTimo Kreuzer;       EAX, ECX
48*04e0dc4aSTimo Kreuzer;
49*04e0dc4aSTimo Kreuzer;Exceptions:
50*04e0dc4aSTimo Kreuzer;
51*04e0dc4aSTimo Kreuzer;*******************************************************************************
52*04e0dc4aSTimo Kreuzer
53*04e0dc4aSTimo Kreuzerpage
54*04e0dc4aSTimo Kreuzer;***
55*04e0dc4aSTimo Kreuzer;char *strcpy(dst, src) - copy one string over another
56*04e0dc4aSTimo Kreuzer;
57*04e0dc4aSTimo Kreuzer;Purpose:
58*04e0dc4aSTimo Kreuzer;       Copies the string src into the spot specified by
59*04e0dc4aSTimo Kreuzer;       dest; assumes enough room.
60*04e0dc4aSTimo Kreuzer;
61*04e0dc4aSTimo Kreuzer;       Algorithm:
62*04e0dc4aSTimo Kreuzer;       char * strcpy (char * dst, char * src)
63*04e0dc4aSTimo Kreuzer;       {
64*04e0dc4aSTimo Kreuzer;           char * cp = dst;
65*04e0dc4aSTimo Kreuzer;
66*04e0dc4aSTimo Kreuzer;           while( *cp++ = *src++ )
67*04e0dc4aSTimo Kreuzer;                   ;               /* Copy src over dst */
68*04e0dc4aSTimo Kreuzer;           return( dst );
69*04e0dc4aSTimo Kreuzer;       }
70*04e0dc4aSTimo Kreuzer;
71*04e0dc4aSTimo Kreuzer;Entry:
72*04e0dc4aSTimo Kreuzer;       char * dst - string over which "src" is to be copied
73*04e0dc4aSTimo Kreuzer;       const char * src - string to be copied over "dst"
74*04e0dc4aSTimo Kreuzer;
75*04e0dc4aSTimo Kreuzer;Exit:
76*04e0dc4aSTimo Kreuzer;       The address of "dst" in EAX
77*04e0dc4aSTimo Kreuzer;
78*04e0dc4aSTimo Kreuzer;Uses:
79*04e0dc4aSTimo Kreuzer;       EAX, ECX
80*04e0dc4aSTimo Kreuzer;
81*04e0dc4aSTimo Kreuzer;Exceptions:
82*04e0dc4aSTimo Kreuzer;*******************************************************************************
83*04e0dc4aSTimo Kreuzer
84*04e0dc4aSTimo Kreuzer
85*04e0dc4aSTimo Kreuzer        CODESEG
86*04e0dc4aSTimo Kreuzer
87*04e0dc4aSTimo Kreuzer%       public  strcat, strcpy      ; make both functions available
88*04e0dc4aSTimo Kreuzerstrcpy  proc \
89*04e0dc4aSTimo Kreuzer        dst:ptr byte, \
90*04e0dc4aSTimo Kreuzer        src:ptr byte
91*04e0dc4aSTimo Kreuzer
92*04e0dc4aSTimo Kreuzer        OPTION PROLOGUE:NONE, EPILOGUE:NONE
93*04e0dc4aSTimo Kreuzer
94*04e0dc4aSTimo Kreuzer        push    edi                 ; preserve edi
95*04e0dc4aSTimo Kreuzer        mov     edi,[esp+8]         ; edi points to dest string
96*04e0dc4aSTimo Kreuzer        jmp     short copy_start
97*04e0dc4aSTimo Kreuzer
98*04e0dc4aSTimo Kreuzerstrcpy  endp
99*04e0dc4aSTimo Kreuzer
100*04e0dc4aSTimo Kreuzer        align   16
101*04e0dc4aSTimo Kreuzer
102*04e0dc4aSTimo Kreuzerstrcat  proc \
103*04e0dc4aSTimo Kreuzer        dst:ptr byte, \
104*04e0dc4aSTimo Kreuzer        src:ptr byte
105*04e0dc4aSTimo Kreuzer
106*04e0dc4aSTimo Kreuzer        OPTION PROLOGUE:NONE, EPILOGUE:NONE
107*04e0dc4aSTimo Kreuzer
108*04e0dc4aSTimo Kreuzer        .FPO    ( 0, 2, 0, 0, 0, 0 )
109*04e0dc4aSTimo Kreuzer
110*04e0dc4aSTimo Kreuzer        mov     ecx,[esp+4]         ; ecx -> dest string
111*04e0dc4aSTimo Kreuzer        push    edi                 ; preserve edi
112*04e0dc4aSTimo Kreuzer        test    ecx,3               ; test if string is aligned on 32 bits
113*04e0dc4aSTimo Kreuzer        je      short find_end_of_dest_string_loop
114*04e0dc4aSTimo Kreuzer
115*04e0dc4aSTimo Kreuzerdest_misaligned:                    ; simple byte loop until string is aligned
116*04e0dc4aSTimo Kreuzer        mov     al,byte ptr [ecx]
117*04e0dc4aSTimo Kreuzer        add     ecx,1
118*04e0dc4aSTimo Kreuzer        test    al,al
119*04e0dc4aSTimo Kreuzer        je      short start_byte_3
120*04e0dc4aSTimo Kreuzer        test    ecx,3
121*04e0dc4aSTimo Kreuzer        jne     short dest_misaligned
122*04e0dc4aSTimo Kreuzer
123*04e0dc4aSTimo Kreuzer        align   4
124*04e0dc4aSTimo Kreuzer
125*04e0dc4aSTimo Kreuzerfind_end_of_dest_string_loop:
126*04e0dc4aSTimo Kreuzer        mov     eax,dword ptr [ecx] ; read 4 bytes
127*04e0dc4aSTimo Kreuzer        mov     edx,7efefeffh
128*04e0dc4aSTimo Kreuzer        add     edx,eax
129*04e0dc4aSTimo Kreuzer        xor     eax,-1
130*04e0dc4aSTimo Kreuzer        xor     eax,edx
131*04e0dc4aSTimo Kreuzer        add     ecx,4
132*04e0dc4aSTimo Kreuzer        test    eax,81010100h
133*04e0dc4aSTimo Kreuzer        je      short find_end_of_dest_string_loop
134*04e0dc4aSTimo Kreuzer        ; found zero byte in the loop
135*04e0dc4aSTimo Kreuzer        mov     eax,[ecx - 4]
136*04e0dc4aSTimo Kreuzer        test    al,al               ; is it byte 0
137*04e0dc4aSTimo Kreuzer        je      short start_byte_0
138*04e0dc4aSTimo Kreuzer        test    ah,ah               ; is it byte 1
139*04e0dc4aSTimo Kreuzer        je      short start_byte_1
140*04e0dc4aSTimo Kreuzer        test    eax,00ff0000h       ; is it byte 2
141*04e0dc4aSTimo Kreuzer        je      short start_byte_2
142*04e0dc4aSTimo Kreuzer        test    eax,0ff000000h      ; is it byte 3
143*04e0dc4aSTimo Kreuzer        je      short start_byte_3
144*04e0dc4aSTimo Kreuzer        jmp     short find_end_of_dest_string_loop
145*04e0dc4aSTimo Kreuzer                                    ; taken if bits 24-30 are clear and bit
146*04e0dc4aSTimo Kreuzer                                    ; 31 is set
147*04e0dc4aSTimo Kreuzerstart_byte_3:
148*04e0dc4aSTimo Kreuzer        lea     edi,[ecx - 1]
149*04e0dc4aSTimo Kreuzer        jmp     short copy_start
150*04e0dc4aSTimo Kreuzerstart_byte_2:
151*04e0dc4aSTimo Kreuzer        lea     edi,[ecx - 2]
152*04e0dc4aSTimo Kreuzer        jmp     short copy_start
153*04e0dc4aSTimo Kreuzerstart_byte_1:
154*04e0dc4aSTimo Kreuzer        lea     edi,[ecx - 3]
155*04e0dc4aSTimo Kreuzer        jmp     short copy_start
156*04e0dc4aSTimo Kreuzerstart_byte_0:
157*04e0dc4aSTimo Kreuzer        lea     edi,[ecx - 4]
158*04e0dc4aSTimo Kreuzer;       jmp     short copy_start
159*04e0dc4aSTimo Kreuzer
160*04e0dc4aSTimo Kreuzer;       edi points to the end of dest string.
161*04e0dc4aSTimo Kreuzercopy_start::
162*04e0dc4aSTimo Kreuzer        mov     ecx,[esp+0ch]       ; ecx -> sorc string
163*04e0dc4aSTimo Kreuzer        test    ecx,3               ; test if string is aligned on 32 bits
164*04e0dc4aSTimo Kreuzer        je      short main_loop_entrance
165*04e0dc4aSTimo Kreuzer
166*04e0dc4aSTimo Kreuzersrc_misaligned:                     ; simple byte loop until string is aligned
167*04e0dc4aSTimo Kreuzer        mov     dl,byte ptr [ecx]
168*04e0dc4aSTimo Kreuzer        add     ecx,1
169*04e0dc4aSTimo Kreuzer        test    dl,dl
170*04e0dc4aSTimo Kreuzer        je      short byte_0
171*04e0dc4aSTimo Kreuzer        mov     [edi],dl
172*04e0dc4aSTimo Kreuzer        add     edi,1
173*04e0dc4aSTimo Kreuzer        test    ecx,3
174*04e0dc4aSTimo Kreuzer        jne     short src_misaligned
175*04e0dc4aSTimo Kreuzer        jmp     short main_loop_entrance
176*04e0dc4aSTimo Kreuzer
177*04e0dc4aSTimo Kreuzermain_loop:                          ; edx contains first dword of sorc string
178*04e0dc4aSTimo Kreuzer        mov     [edi],edx           ; store one more dword
179*04e0dc4aSTimo Kreuzer        add     edi,4               ; kick dest pointer
180*04e0dc4aSTimo Kreuzermain_loop_entrance:
181*04e0dc4aSTimo Kreuzer        mov     edx,7efefeffh
182*04e0dc4aSTimo Kreuzer        mov     eax,dword ptr [ecx] ; read 4 bytes
183*04e0dc4aSTimo Kreuzer
184*04e0dc4aSTimo Kreuzer        add     edx,eax
185*04e0dc4aSTimo Kreuzer        xor     eax,-1
186*04e0dc4aSTimo Kreuzer
187*04e0dc4aSTimo Kreuzer        xor     eax,edx
188*04e0dc4aSTimo Kreuzer        mov     edx,[ecx]           ; it's in cache now
189*04e0dc4aSTimo Kreuzer
190*04e0dc4aSTimo Kreuzer        add     ecx,4               ; kick dest pointer
191*04e0dc4aSTimo Kreuzer        test    eax,81010100h
192*04e0dc4aSTimo Kreuzer
193*04e0dc4aSTimo Kreuzer        je      short main_loop
194*04e0dc4aSTimo Kreuzer        ; found zero byte in the loop
195*04e0dc4aSTimo Kreuzer; main_loop_end:
196*04e0dc4aSTimo Kreuzer        test    dl,dl               ; is it byte 0
197*04e0dc4aSTimo Kreuzer        je      short byte_0
198*04e0dc4aSTimo Kreuzer        test    dh,dh               ; is it byte 1
199*04e0dc4aSTimo Kreuzer        je      short byte_1
200*04e0dc4aSTimo Kreuzer        test    edx,00ff0000h       ; is it byte 2
201*04e0dc4aSTimo Kreuzer        je      short byte_2
202*04e0dc4aSTimo Kreuzer        test    edx,0ff000000h      ; is it byte 3
203*04e0dc4aSTimo Kreuzer        je      short byte_3
204*04e0dc4aSTimo Kreuzer        jmp     short main_loop     ; taken if bits 24-30 are clear and bit
205*04e0dc4aSTimo Kreuzer                                    ; 31 is set
206*04e0dc4aSTimo Kreuzerbyte_3:
207*04e0dc4aSTimo Kreuzer        mov     [edi],edx
208*04e0dc4aSTimo Kreuzer        mov     eax,[esp+8]         ; return in eax pointer to dest string
209*04e0dc4aSTimo Kreuzer        pop     edi
210*04e0dc4aSTimo Kreuzer        ret
211*04e0dc4aSTimo Kreuzerbyte_2:
212*04e0dc4aSTimo Kreuzer        mov     [edi],dx
213*04e0dc4aSTimo Kreuzer        mov     eax,[esp+8]         ; return in eax pointer to dest string
214*04e0dc4aSTimo Kreuzer        mov     byte ptr [edi+2],0
215*04e0dc4aSTimo Kreuzer        pop     edi
216*04e0dc4aSTimo Kreuzer        ret
217*04e0dc4aSTimo Kreuzerbyte_1:
218*04e0dc4aSTimo Kreuzer        mov     [edi],dx
219*04e0dc4aSTimo Kreuzer        mov     eax,[esp+8]         ; return in eax pointer to dest string
220*04e0dc4aSTimo Kreuzer        pop     edi
221*04e0dc4aSTimo Kreuzer        ret
222*04e0dc4aSTimo Kreuzerbyte_0:
223*04e0dc4aSTimo Kreuzer        mov     [edi],dl
224*04e0dc4aSTimo Kreuzer        mov     eax,[esp+8]         ; return in eax pointer to dest string
225*04e0dc4aSTimo Kreuzer        pop     edi
226*04e0dc4aSTimo Kreuzer        ret
227*04e0dc4aSTimo Kreuzer
228*04e0dc4aSTimo Kreuzerstrcat  endp
229*04e0dc4aSTimo Kreuzer
230*04e0dc4aSTimo Kreuzer        end
231*04e0dc4aSTimo Kreuzer
232