如何在Assembly中清除缓冲区?

时间:2016-08-25 20:20:26

标签: assembly x86

我在汇编程序中进行编程,并且我已经创建了一个辅助缓冲区来临时存储一些字符,然后将它们写入文件。问题是我必须多次使用辅助缓冲区,所以我需要清理/恢复它,我不知道如何实现这一点。

我在Linux上使用i386架构。

PD:我忘记了,这就是我宣布缓冲区的方式:

section .bss           
      auxBuffer resb 1000

1 个答案:

答案 0 :(得分:2)

通过写入来清除缓冲区 显然,内存中的位置永远不会是空的,因此有效清除缓冲区意味着用零填充它 没有什么可以阻止你填充0xCAFEBABE十六进制值,但零是标准约定。

mov dword ptr [buffer],0
mov dword ptr [buffer+4],0
mov ...              +8],0
....

显然,这是清除缓冲区的一种愚蠢方式。如果缓冲区是40,000字节,则需要10,000条指令;可能但浪费。

相反,你编写一个循环并使用计数器来跟踪你到目前为止所写的内容。

mov ecx,10000        //10000 x 4 = 40.000 bytes
lea edx,[buffer]     //point edx to the start of the block to be cleared.  
xor eax,eax          //xor reg,reg is the same as mov reg,0, but faster.
@loop:
mov [edx+ecx*4],eax  //fill the buffer starting at the end.
dec ecx              //decrease the counter; also moving the destination.   
jnz @loop            //if ecx <> 0 (Non-Zero) then repeat.
ret                  //we are done, return.

ecx作为计数器和作为缓冲区指针的双重任务 请注意,xor eax,eax是将寄存器设置为零的标准方法。它比mov eax,0短并且速度更快,因为CPU是硬连线的,可以给予前一条指令优惠待遇 然而,这样做的方式更短。
x86具有接受rep (repeat) prefix的所谓字符串指令 如果这样前缀,则指令将运行ecx次。

push edi           //on Windows edi is non-volatile (callee-save), so save it.
lea edi,[buffer]   //edi is the start of the buffer.
xor eax,eax        //fill the buffer with zeros.
mov ecx,10000      
rep stosd          //store string with 10000 dwords = 40000 bytes.
pop edi            //restore edi to its previous value.
ret                //return.

stosd(每个dword的商店字符串)使用edi作为其目标,ecx作为计数器,eax作为来源。
请注意,stosd是一个复杂的指令。现代x86 CPU通过简单的指令更快地工作,并且通常优化(!)版本的第二个代码段比简单使用rep stosd更快。 默认情况下, rep stosd在Windows / Linux上向前移动。您可以设置CPU使其向后移动,但之后您必须恢复方向设置。

在Windows eax下,ecxedx是易变的,可以随意更改。在调用之间需要保留所有其他寄存器。