如何在程序集 x86-64 中保存字符串临时变量

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

我是汇编的新手,我必须在汇编 x86-64 中编写 memmove 函数,它说:

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.

然而,我没有找到在程序集中保存临时字符串的方法,这就是我发布此内容的原因。

我试图放入 rax 寄存器,但出现分段错误:

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

顺便说一下,我正在使用 nasm -f elf64 memmove.asm 构建

谢谢。

机器指令MOVSB 将成为您复制内存区域的朋友。它从 RSI 寻址的内存中复制一个字节 到 RDI 寻址的内存,然后将两个寄存器修改为下一个元素(字节)。

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

我们可以通过这种方式可视化 MOVSB 之前的内存布局

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

MOVSB 之后

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

使用指令前缀 REP 重复 RCX 次。 之后

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

当 Src 和 Dest 区域重叠时,这不会按预期工作 - 而不是 0120123489 我们有 0120120189。 当目标字段在源上方(RDI>RSI)时,我们必须向后复制(设置方向标志) 并从指向字段末尾的寄存器开始。

   LEA RSI,[SrcLast]
   LEA RDI,[DestLast]
   MOV RCX,DestLast-Dest1st+1

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

之后

   STD
   REP MOVSB

RSI   RDI
 |     |          
   0 1 2 0 1 2 3 4 8 9

源字段被逐字复制到目标,没有临时数组,不浪费内存和时钟。向后复制后应将方向标志重置为其默认状态,这是大多数操作系统和库函数的接口所期望的。