2015-01-03 140 views
2

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

我首先想到的是,ecx寄存器用作循环计数器,但查不到,我已经使用了stdcall功能尚未保存的ecx值后,我以为不然。

是否有保存的寄存器(通过至少大多数使用的调用约定)被保留?

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

+0

你可以推'ecx'堆栈上和它之前,你'ret'恢复,或者你可以只使用另一个寄存器 –

+1

'推ECX '在调用返回之后,每次通过循环时使'stdcall'和'pop ecx'之前。 – lurker

回答

2

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

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

loop label 

...与...

dec ebp 
jnz label 

...这是更快呢(因为AMD(以及后来的英特尔,当他们追了上来,以MHz为单位)人为地减慢了指令的速度,否则Windows®和一些Turbo Pascal编译软件崩溃)。

,或者你只是保存在柜台之间:

label: 
    push ecx 
    call func 
    pop ecx 
    loop label 

两者都是标准的战略。

2

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

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

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

引用昂纳雾的优秀论文Calling conventions for different C++ compilers and operating systems

6寄存器用法

对寄存器的使用的规则依赖于操作系统,如表4所示。暂存寄存器是寄存器,可以是用于没有限制的临时存储(也称为呼叫者保存或易失性寄存器)。被调用保存寄存器是在使用它们之前必须保存的寄存器,并在使用它们(也称为非易失性寄存器)后进行恢复。你可以依靠具有呼叫作为呼叫之前之后的值相同,这些寄存器...

enter image description here

...

参见:

相关问题