3

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.

MacBess
  • 61
  • 4
  • 2
    That's nonsense, overlapping regions are handled by copying in the appropriate direction. If you really want a temporary array, you will need to allocate it somewhere. – Jester Feb 17 '20 at 18:39
  • 3
    Key word is "as though". Real implementations don't actually use a temporary array and neither should yours. You may find it helpful to try and write the function in C before trying it in assembly. – Nate Eldredge Feb 17 '20 at 19:56

1 Answers1

1

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.

vitsoft
  • 5,515
  • 1
  • 18
  • 31