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

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

我首先想到的是, ecx寄存器被用作循环计数器,但是在发现我使用的stdcall函数没有保留ecx的值之后,我想不然了。

是否有保存的寄存器(至less大部分使用的调用约定)被保存?

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

你可以使用任何通用寄存器,偶尔也可以使用其他的寄存器作为循环计数器(当然不是堆栈指针)。

要么你用一个手动循环,即替换…

 loop label 

… …

 dec ebp jnz label 

反正速度更快(因为AMD(后来英特尔,当他们赶上了,MHz的时候)人为地减慢了loop指令,否则,Windows®和一些Turbo Pascal编译软件崩溃了)。

或者你只需​​将柜台保存在:

 label: push ecx call func pop ecx loop label 

两者都是标准策略。

是否有保存的寄存器(至少大部分使用的调用约定)被保存?

如果您的循环代码不会调用任何外部实体,您可以在自己的代码中选择任何免费注册。

如果您的循环代码将调用一个外部实体,其中唯一的保证合同是ABI和调用约定,那么您必须保存/恢复您的寄存器,并根据具体情况选择寄存器。

引用Agner Fog的优秀论文针对不同C ++编译器和操作系统的调用约定 :

6注册使用情况

寄存器使用的规则取决于操作系统,如表4所示。暂存寄存器是可用于临时存储而不受限制的寄存器(也称为调用者保存或易失性寄存器)。 被调用保存寄存器是在使用它们之前必须保存的寄存器,并在使用它们(也称为非易失性寄存器)后进行恢复。 在通话之后,您可以依靠这些具有相同值的寄存器来调用…

在这里输入图像说明

也可以看看:

  • Wikipedia:x86调用约定