我在汇编程序中进行编程,并且我已经创建了一个辅助缓冲区来临时存储一些字符,然后将它们写入文件。问题是我必须多次使用辅助缓冲区,所以我需要清理/恢复它,我不知道如何实现这一点。
我在Linux上使用i386架构。
PD:我忘记了,这就是我宣布缓冲区的方式:section .bss
auxBuffer resb 1000
答案 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
下,ecx
和edx
是易变的,可以随意更改。在调用之间需要保留所有其他寄存器。