我可以使用寄存器作为循环计数器吗?

时间:2015-01-03 13:54:40

标签: windows assembly nasm calling-convention

由于函数的调用约定说明了哪个寄存器被保留,寄存器可以用作循环计数器吗?

我首先认为ecx寄存器用作循环计数器,但在发现我使用的stdcall函数未保留ecx的值后,我想否则。

是否有保证的寄存器(至少通过使用的调用约定)?

注意:我在使用堆栈变量作为循环计数器时没有问题,我只是想确保它是唯一的方法。

2 个答案:

答案 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所示。划痕寄存器是可以无限制地用于临时存储的寄存器(也称为调用者保存或易失性寄存器)。被调用者保存寄存器是在使用它们之前必须保存的寄存器,并在使用它们之后进行恢复(也称为非易失性寄存器)。在通话之后,您可以依赖这些具有相同值的寄存器...

     

enter image description here

     

...

另见: