由于函数的调用约定说明了哪个寄存器被保留,寄存器可以用作循环计数器吗?
我首先认为ecx
寄存器用作循环计数器,但在发现我使用的stdcall
函数未保留ecx
的值后,我想否则。
是否有保证的寄存器(至少通过使用的调用约定)?
注意:我在使用堆栈变量作为循环计数器时没有问题,我只是想确保它是唯一的方法。
答案 0 :(得分:2)
你可以使用任何通用寄存器,偶尔使用其他寄存器作为循环计数器(当然不是堆栈指针☺)。
您可以使用一个手动循环,即替换...
loop label
...与......
dec ebp
jnz label
...无论如何都是更快的(因为AMD(以及后来的英特尔,当它们赶上时,以MHz为单位)人为地减慢了loop
指令,否则,Windows®和一些Turbo Pascal编译的软件崩溃了。 / p>
或者您只需将计数器保存在:
之间label:
push ecx
call func
pop ecx
loop label
两者都是标准策略。
答案 1 :(得分:2)
是否有保证的寄存器(至少通过使用的调用约定)?
如果您的循环代码不会调用任何外部实体,您可以在自己的代码中选择任何免费注册。
如果您的循环代码将调用外部实体,其中唯一保证的合同是ABI并且调用约定,那么您必须保存/恢复寄存器并逐个选择寄存器。
引用Agner Fog的优秀论文Calling conventions for different C++ compilers and operating systems:
6注册用法
寄存器使用规则取决于操作系统,如表4所示。划痕寄存器是可以无限制地用于临时存储的寄存器(也称为调用者保存或易失性寄存器)。被调用者保存寄存器是在使用它们之前必须保存的寄存器,并在使用它们之后进行恢复(也称为非易失性寄存器)。在通话之后,您可以依赖这些具有相同值的寄存器...
...
另见: