从 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
,但我也想避免 esi
和 edi
之间可能存在内存重叠的情况。我相信,使用缓冲区之类的东西可以做到这一点(我使用的术语不正确吗?)。
这里有两件事。首先,重叠内存通常通过切换完成复制的方向来处理。你应该首先说服自己,无论两个区域如何重叠,要么从每个块中的最低地址开始,从源复制到目标,为每个字节递增指针;或者从每个块中的最高地址开始并进行同样的复制,但随后递减指针将起作用。
使用中间缓冲区需要将副本平铺在固定大小的缓冲区上,这仍然需要操纵方向,或者调用例如malloc,这主要是速度慢,但也需要弄清楚如何从程序集中调用函数。
首先,我建议在 C/C++ 或类似语言中写出方向条件和两个循环。 (带有指针的语言会有所帮助。)即在 C 中编写您自己的 memmove 副本。
此时,您需要将 if 语句、循环以及从源到目标的复制翻译成程序集。这一切都非常简单,评论中有一些关于如何使用 x86 指令为您执行计数循环的建议。 (请注意,如果使用内置支持,您需要了解 x86 方向标志,例如 CLD 和 STD 指令。我会从长手开始,然后转向使用 REP* 支持。)
一个很好地处理这个问题的方法是编写 C/C++ 代码并使用编译器的汇编输出标志(例如大多数 UNIXy 系统上的 -S)。
我一直在思考如何通过缓冲区进行内存复制。
我的函数的参数是: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
,但我也想避免 esi
和 edi
之间可能存在内存重叠的情况。我相信,使用缓冲区之类的东西可以做到这一点(我使用的术语不正确吗?)。
这里有两件事。首先,重叠内存通常通过切换完成复制的方向来处理。你应该首先说服自己,无论两个区域如何重叠,要么从每个块中的最低地址开始,从源复制到目标,为每个字节递增指针;或者从每个块中的最高地址开始并进行同样的复制,但随后递减指针将起作用。
使用中间缓冲区需要将副本平铺在固定大小的缓冲区上,这仍然需要操纵方向,或者调用例如malloc,这主要是速度慢,但也需要弄清楚如何从程序集中调用函数。
首先,我建议在 C/C++ 或类似语言中写出方向条件和两个循环。 (带有指针的语言会有所帮助。)即在 C 中编写您自己的 memmove 副本。
此时,您需要将 if 语句、循环以及从源到目标的复制翻译成程序集。这一切都非常简单,评论中有一些关于如何使用 x86 指令为您执行计数循环的建议。 (请注意,如果使用内置支持,您需要了解 x86 方向标志,例如 CLD 和 STD 指令。我会从长手开始,然后转向使用 REP* 支持。)
一个很好地处理这个问题的方法是编写 C/C++ 代码并使用编译器的汇编输出标志(例如大多数 UNIXy 系统上的 -S)。