从 ESI 复制到缓冲区再到 EDI

Copying from ESI to Buffer to EDI

我一直在思考如何通过缓冲区进行内存复制。

我的函数的参数是:void* dest, void* src, size_t length

我这样设置我的函数:

push ebp
mov ebp, esp
push edi
push esi
push ebx

mov edi, [ebp+0x8] ; this is dest
mov esi, [ebp+0xc] ; this is src
mov ecx, [ebp+0x10] ; this is length

我有点不知道下一步该怎么做。我知道我需要创建一个缓冲区,因为我可能会有重叠的内存,但我不确定如何在我的函数中设置我的缓冲区。

一旦我这样做了,我会想象下面的代码看起来像(假设 ebx 作为缓冲区):

mov ebx, [esi+4*ecx]
mov edi, [ebx]

pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp

提前致谢!

编辑:为了澄清,我将我的评论之一放在这里:本质上,我想获取存储在 esi 中的数据并将其移动到 edi,但我也想避免 esiedi 之间可能存在内存重叠的情况。我相信,使用缓冲区之类的东西可以做到这一点(我使用的术语不正确吗?)。

这里有两件事。首先,重叠内存通常通过切换完成复制的方向来处理。你应该首先说服自己,无论两个区域如何重叠,要么从每个块中的最低地址开始,从源复制到目标,为每个字节递增指针;或者从每个块中的最高地址开始并进行同样的复制,但随后递减指针将起作用。

使用中间缓冲区需要将副本平铺在固定大小的缓冲区上,这仍然需要操纵方向,或者调用例如malloc,这主要是速度慢,但也需要弄清楚如何从程序集中调用函数。

首先,我建议在 C/C++ 或类似语言中写出方向条件和两个循环。 (带有指针的语言会有所帮助。)即在 C 中编写您自己的 memmove 副本。

此时,您需要将 if 语句、循环以及从源到目标的复制翻译成程序集。这一切都非常简单,评论中有一些关于如何使用 x86 指令为您执行计数循环的建议。 (请注意,如果使用内置支持,您需要了解 x86 方向标志,例如 CLD 和 STD 指令。我会从长手开始,然后转向使用 REP* 支持。)

一个很好地处理这个问题的方法是编写 C/C++ 代码并使用编译器的汇编输出标志(例如大多数 UNIXy 系统上的 -S)。