如何在 x86 程序集 (MASM) 中复制以零结尾的字符串,包括以 0 结尾的字符串?

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

我正在尝试编写一个函数,用于将以零结尾的字符串复制到另一个包括以 0 结尾的字符串。

在我调用 stringCopy(str1, str2); 之后输出应该是 Good-bye0ld0 但是 Good -再见 :(我错过了什么? 如何打印正确的结果?

;------------------ 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

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

IIUC,您忽略了 C/C++ 字符串处理函数在遇到第一个空字节时停止的事实(这就是字符串被称为 "zero-terminated" 的原因)。因此在将整个 str2 字符串复制到 str1 之后,标准 C++ 库将打印它的前 8 个字节。

How to print the correct result?

这是正确的结果。如果您希望打印空字节或初始 str1 内容的字符数,您可以在 str1 的初始长度上循环使用 [=15 一次放置一个字符=].您可能会看到一些与空字节相对应的微笑或空字符。

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