2015-01-03 237 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

...

參見:

相關問題