如何在程序集 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
源字段被逐字复制到目标,没有临时数组,不浪费内存和时钟。向后复制后应将方向标志重置为其默认状态,这是大多数操作系统和库函数的接口所期望的。
我是汇编的新手,我必须在汇编 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
源字段被逐字复制到目标,没有临时数组,不浪费内存和时钟。向后复制后应将方向标志重置为其默认状态,这是大多数操作系统和库函数的接口所期望的。