我可以使用寄存器作为循环计数器吗?
Can I use a register as a loop counter?
由于函数的调用约定规定保留了哪些寄存器,寄存器可以用作循环计数器吗?
我一开始以为ecx
寄存器是用来做循环计数器的,后来发现我用过的一个stdcall
函数并没有保留ecx
的值,我不这么认为。
是否有保证(至少通过大多数使用的调用约定)被保留的寄存器?
注意:我在使用堆栈变量作为循环计数器时没有问题,我只是想确保这是唯一的方法。
您可以使用任何通用寄存器,偶尔也可以使用其他寄存器作为循环计数器(当然不是堆栈指针☺)。
要么你用一个手动循环,即替换…
loop label
…与…
dec ebp
jnz label
… 无论如何都更快(因为 AMD(以及后来的英特尔,当他们赶上时,以 MHz 为单位)人为地减慢了 loop
指令,否则 Windows® 和一些 Turbo Pascal编译软件崩溃)。
或者您只是在两者之间保存计数器:
label:
push ecx
call func
pop ecx
loop label
两者都是标准策略。
Is there a register that is guaranteed (by mostly used calling conventions at least) to be preserved?
如果您的循环代码不会调用任何外部实体,您可以在自己的代码中选择任何自由寄存器。
如果您的循环代码将调用外部实体,其中唯一保证的合同是 ABI 和调用约定,那么您必须 save/restore 您的寄存器并选择寄存器 case-by-case。
引用 Agner Fog 的优秀论文Calling conventions for different C++ compilers and operating systems:
6 Register usage
The rules for register usage depend on the operating system, as shown in table 4. Scratch registers are registers that can be used for temporary storage without restrictions (also called caller-save or volatile registers). Callee-save registers are registers that you have to save before using them and restore after using them (also called non-volatile registers). You can rely on these registers having the same value after a call as before the call...
...
另请参阅:
由于函数的调用约定规定保留了哪些寄存器,寄存器可以用作循环计数器吗?
我一开始以为ecx
寄存器是用来做循环计数器的,后来发现我用过的一个stdcall
函数并没有保留ecx
的值,我不这么认为。
是否有保证(至少通过大多数使用的调用约定)被保留的寄存器?
注意:我在使用堆栈变量作为循环计数器时没有问题,我只是想确保这是唯一的方法。
您可以使用任何通用寄存器,偶尔也可以使用其他寄存器作为循环计数器(当然不是堆栈指针☺)。
要么你用一个手动循环,即替换…
loop label
…与…
dec ebp
jnz label
… 无论如何都更快(因为 AMD(以及后来的英特尔,当他们赶上时,以 MHz 为单位)人为地减慢了 loop
指令,否则 Windows® 和一些 Turbo Pascal编译软件崩溃)。
或者您只是在两者之间保存计数器:
label:
push ecx
call func
pop ecx
loop label
两者都是标准策略。
Is there a register that is guaranteed (by mostly used calling conventions at least) to be preserved?
如果您的循环代码不会调用任何外部实体,您可以在自己的代码中选择任何自由寄存器。
如果您的循环代码将调用外部实体,其中唯一保证的合同是 ABI 和调用约定,那么您必须 save/restore 您的寄存器并选择寄存器 case-by-case。
引用 Agner Fog 的优秀论文Calling conventions for different C++ compilers and operating systems:
6 Register usage
The rules for register usage depend on the operating system, as shown in table 4. Scratch registers are registers that can be used for temporary storage without restrictions (also called caller-save or volatile registers). Callee-save registers are registers that you have to save before using them and restore after using them (also called non-volatile registers). You can rely on these registers having the same value after a call as before the call...
...
另请参阅: