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



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

memmove(( 函数将 n 个字节从内存区域 src 复制到内存区域 dest。内存区域可能会重叠:复制就像 src 中的字节首先复制到重叠 src 或 dest 的临时数组中,然后将字节从临时数组复制到 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

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

最新更新