Search code examples
assemblynasmmemmove

Trying to recode memmove in asm


I am using nasm on Ubuntu 16.04, and I'm currently trying to recode the C memmove() function.

Here is my code :

BITS 64

global memmove

memmove:
        push rbp
        mov rbp, rsp
        xor rcx, rcx

while:
        cmp rcx, rdx
        je end
        mov r10b, byte [rsi + rcx]
        mov byte [rdi + rcx], r10b
        inc rcx
        jmp while

end:
        mov rax, rdi
        leave
        ret

I'm calling it this way :

char *str = strdup("Salutation");
printf("%s, %s\n", (char *)memmove(str + 3, str, 5), str);

Expected output is :

Saluton, SalSaluton

But I get :

SalSaon, SalSalSaon

For some reasons, when I get to the fourth character, it goes back to the begining of my string rsi. My question is why? What am I doing wrong?

PS : The same problem happens every three characters, like if it could not go futher, and had to go back to the first one.

Thanks in advance.


Solution

  • In C there are two functions: memmove and memcpy

    The difference is that memcpy is a bit faster but it does not allow the destination memory to overlap the source memory.

    What you implemented is memcpy, not memmove!

    Let's implement memcpy in C (and not in Assembler) to see what is happening:

    for(i=0; i<count; i++)
    {
        destination[i]=source[i];
    }
    

    Let's create a char array with the content "Hello world example" and perform a memcpy(&(array[6]), &(array[1]), 10);.

    When the loop is executed the first time the letter "w" will be overwritten by an "e" and will be gone forever!

    The memmove function however will check if the source address is before or after the destination address and if the source address is before the destination address it will perfom the loop backwards:

    for(i=count-1; i>=0; i--)
    

    By the way: Why didn'd you use the movsb instruction?