PROWAREtech
x86 Assembly: wcscpy Procedure
Use MASM for Visual C++ Express Edition 2005 to compile this procedure.
This procedure, wcscpy_asm
, copies a wchar_t
(16-bit) string from the source to the destination and returns the destination pointer.
TITLE 'extern "C" wchar_t *wcscpy_asm(wchar_t *destination, const wchar_t *source);'
.386P
.model FLAT
PUBLIC _wcscpy_asm
_TEXT SEGMENT
_wcscpy_asm PROC NEAR
mov edi, DWORD PTR [esp+8] ; source
mov ecx, 0FFFFFFFFh
xor eax, eax
cld
repne scasw
xor ecx, 0FFFFFFFFh
mov esi, DWORD PTR [esp+8] ; source
mov edi, DWORD PTR [esp+4] ; destination
rep movsw
mov eax, DWORD PTR [esp+4] ; destination
ret 0
_wcscpy_asm ENDP
_TEXT ENDS
END
This procedure, wcscpy2_asm
, copies a wchar_t
(16-bit) string from the source to the destination and returns a pointer
to the end of the destination so that another string can be concatenated.
The default behavior of wcscpy
is to return the destination
buffer but as is obvious below, it is much more useful to return
the end
of the text in the destination
.
TITLE 'extern "C" wchar_t *wcscpy2_asm(wchar_t *destination, const wchar_t *source);'
.386P
.model FLAT
PUBLIC _wcscpy2_asm
_TEXT SEGMENT
_wcscpy2_asm PROC NEAR
mov edi, DWORD PTR [esp+8] ; source
mov ecx, 0FFFFFFFFh
xor eax, eax
cld
repne scasw
mov eax, DWORD PTR [esp+4] ; destination
xor ecx, 0FFFFFFFFh
shl ecx, 1
add eax, ecx
sub eax, 2
shr ecx, 1
mov esi, DWORD PTR [esp+8] ; source
mov edi, DWORD PTR [esp+4] ; destination
rep movsw
ret 0
_wcscpy2_asm ENDP
_TEXT ENDS
END
This example C++ code uses this function.
#include <stdlib.h>
extern "C" wchar_t * wcscpy2_asm(wchar_t *destination, const wchar_t *source);
wchar_t str[100], *end;
int length;
end = wcscpy2_asm(str, L"How ");
end = wcscpy2_asm(end, L"now ");
end = wcscpy2_asm(end, L"brown ");
end = wcscpy2_asm(end, L"cow!");
length = end - str;
// or simply
length = wcscpy2_asm(wcscpy2_asm(wcscpy2_asm(wcscpy2_asm(str, L"How "), L"now "), L"brown "), L"cow!") - str;
// str == L"How now brown cow!"
// length == 18
Here is another implementation of the above version that returns the end of the text in the destination but without using the string primitive instructions. It might be faster.
TITLE 'extern "C" wchar_t *wcscpy2_alt_asm(wchar_t *destination, const wchar_t *source);'
.386P
.model FLAT
PUBLIC _wcscpy2_alt_asm
_TEXT SEGMENT
_wcscpy2_alt_asm PROC NEAR
mov edx, DWORD PTR [esp+8] ; source
mov cx, WORD PTR [edx]
test cx, cx
mov eax, DWORD PTR [esp+4] ; destination
je SHORT label2
label1:
mov WORD PTR [eax], cx
add edx, 2
xor ecx, ecx
mov cx, WORD PTR [edx]
add eax, 2
test cx, cx
jne SHORT label1
label2:
mov WORD PTR [eax], 0
ret 0
_wcscpy2_alt_asm ENDP
_TEXT ENDS
END