我正在汇编程序中编程,我创建了一个辅助缓冲区来临时存储一些字符,然后将它们写入文件中。问题是,我必须多次使用辅助缓冲区,所以我需要清理/恢复它,而我不知道如何实现它。
我在Linux中使用i386架构。
PD:我忘了,我是这样声明缓冲区的:
section .bss
auxBuffer resb 1000
发布于 2016-08-30 15:24:51
您可以通过写入缓冲区来清除缓冲区。
显然,内存中的位置永远不会真正为空,因此有效地清除缓冲区意味着用零填充缓冲区。
没有什么可以阻止您用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有所谓的接受 (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
(s̲t̲o̲re s̲tring per d̲word)使用edi
作为其D̲建立,ecx
作为C̲ounter,eax
作为源。
注意,stosd
是一个复杂的指令。现代x86 CPU的工作速度更快,使用简单的指令,而且通常是经过优化的(!)第二个代码片段的版本将比简单使用rep stosd
工作得更快。
默认情况下,rep stosd
在Windows/Linux上向前移动。您可以设置CPU以使其向后移动,但随后必须恢复方向设置。
在windows eax
下,ecx
和edx
是不稳定的,可以随意更改。所有其他寄存器都需要在呼叫之间保存。
https://stackoverflow.com/questions/39154103
复制相似问题