assemblyx86-64memmove

How to save a string temporary variable in assembly x86-64


Im new to assembly and I've to write the memmove function in assembly x86-64, and it said :

The memmove() function copies n bytes from memory area src to memory area dest. The memory areas may overlap: copying takes place as though the bytes in src are first copied into a temporary array that does not overlap src or dest, and the bytes are then copied from the temporary array to dest.

Nevertheless, I don't find a way to save a temporary string in assembly, and that's why I am posting this.

I tried to put in rax register, but I got a segmentation fault :

mov r8b, byte [rsi + rcx] ; rsi is source string
mov byte [rax + rcx], r8b

By the way, I'm using nasm -f elf64 memmove.asm on my build

Thank you.


Solution

  • Machine instruction MOVSB will be your friend in copying memory areas. It copies one byte from memory addressed by RSI to the memory addressed by RDI and then modifies both registers to the next element (byte).

    SECTION .data 
    Memory   DB '0123456789'
    Src1st   EQU Memory+0
    SrcLast  EQU Memory+4
    Dest1st  EQU Memory+3
    DestLast EQU Memory+7
    SECTION .text
       LEA RSI,[Src1st]
       LEA RDI,[Dest1st]
       CLD
    

    We can visualize memory layout before MOVSB this way

      RSI   RDI
       |     |
       0 1 2 3 4 5 6 7 8 9 
       _________        Src  
             _________  Dest  
    

    After MOVSB

        RSI   RDI
         |     |
       0 1 2 0 4 5 6 7 8 9 
    

    With instruction prefix REP it is repeated RCX times. After

    MOV RCX,DestLast-Dest1st+1 
    REP MOVSB
                    RSI   RDI
                     |     |
           0 1 2 0 1 2 0 1 8 9
    

    This doesn't work as expected when Src and Dest areas overlap - instead of 0120123489 we've got 0120120189. When the destination field is above the source (RDI>RSI), we must copy backward (set Direction Flag) and start with registers pointing at the end of fields.

       LEA RSI,[SrcLast]
       LEA RDI,[DestLast]
       MOV RCX,DestLast-Dest1st+1
    
              RSI   RDI
               |     |
       0 1 2 3 4 5 6 7 8 9 
    

    After

       STD
       REP MOVSB
    
    RSI   RDI
     |     |          
       0 1 2 0 1 2 3 4 8 9
    

    Source field is copied verbatim to the destination without temporary array, not wasting memory and clocks. The direction flag should be reset to its default state after backward copy, which is expected by interface of most operational systems and library functions.