Search code examples
assemblyx86masmmasm32irvine32

How to copy zero terminated string including terminating 0 in x86 Assembly (MASM)?


I'm trying to write a function for copying zero terminated string to another string including terminating 0.

After I call stringCopy(str1, str2); The output should be Good-bye0ld0 but is Good-bye :( what am I missing ? How to print the correct result?

;------------------ in my .cpp file

extern "C" void __stdcall stringCopy(char[], char[]);


int main()
{

    char str1[] = { 'h','e','l','l','o',' ','w','o','r','l','d',0 };
    cout << str1 << endl;
    char str2[] = { 'G','o','o','d','-','b','y','e',0};
    cout << str2 << endl;

    stringCopy(str1, str2);
    cout << str1 << endl;   ;should be Good-bye0ld0
                            ;but is Good-bye
}


;------------------ in my .asm file
; Copy  zero terminated string2 (including terminating 0)

stringCopy PROC  uses ecx eax esi edi, ;save registers used
                       string1:DWORD,  ;address of string1
                       string2:DWORD   ;address of string2

    cld                                ;forward direction - clear direction flag
    push string2                       ;address of str2 arg to StrlenAsm
    call getStringLength               ;get length of str2
                                       ;called function responsible for stack cleanup
    mov ecx,eax                        ;length of string in ecx for rep
    mov edi,string1                    ;edi gets destination address for copy
    mov esi,string2                    ;esi gets source address for copy
    rep movsb                          ;copy byte from source to desintation ecx times
    mov byte ptr[edi],0                ;null terminate copied string

    ret

stringCopy ENDP


getStringLength PROC uses edi,         ;save edi
           strAdd:DWORD                ;address of string to find length of

    mov edi, strAdd                    ;edi = address of string to get length of
    xor eax,eax                        ;eax to hold length so 0 it out

looptop:
    cmp byte ptr [edi],0               ;have we reached the end of the string yet?
    je done                            ;Yes, done
    inc edi                            ;no, increment to next character
    inc eax                            ;and increment length
    jmp looptop                        ;repeat

done:

ret

getStringLength ENDP

Solution

  • The output should be Good-bye0ld0 but is Good-bye :( what am I missing ?

    IIUC, you are missing the fact that C / C++ string processing functions are stopping at the first encountered null byte (thats why the strings are called "zero-terminated"). Thus after copying the whole str2 string into str1, the standard C++ lib will print the 8 first bytes of it.

    How to print the correct result?

    This is the correct result. If you expect to print the null bytes or the number of characters of the initial str1 content, you can make a loop on the initial length of str1 to put one character at a time with using cout << str1[counter]. You will probably see some smiling or empty characters corresponding to the null bytes.

    int l = sizeof(str1);
    for(int i=0; i<l; i++){
        cout << str1[i];
    }
    cout << endl;