基本知識,7/2 和 6/2 在計算機中的商都為3.C語言的除法不等同於數學意義中的除法。
C語言的除法。采用向零取整的方法。
-______________0_______________+
只有在除數為常量的情況下。編譯器才會出現優化。
1、除數為正數,2的冪的除法
#include main( argc, * iNum =, iNum / , iNum /
對應Release版本的反匯編如下:
+ ; ASCII ; ASCII
是不是感覺很奇怪,怎麼沒有了除法指令。查閱CPU手冊。除法的指令周期數。大得嚇人。具體值得根據cpu型號。翻閱 手冊。
所以。編譯器想盡辦法。就是為了避免產生除法。提高效率。
mov esi, dword ptr [esp+
cdq 是把符號位擴展到 edx. 然後做加法。我們知道。對於被除數為正的情況,其值不變。除以2的冪。等於做 sar右移。
對於被除數為負的情況。那麼由於sar右移。等同於向下取整。由於C語言是向零取整。所以。必須想辦法下整轉上整。就滿足了C語言的向零取整。
於是公式來了。 a為被除數,n為2的冪. (a + 2^n - 1)/2^n
對於 iNum / 2 那就是等於 (iNum + 2 - 1)/2 。常量折疊。等於(iNum + 1)/2。除以2等於sar右移一位。
那麼就完美解決了除以2且無分歧的優化。指令的總周期。相對於div指令要減少很多。
在按照公式推導 iNum /4 的情況。(iNum + 2^2 - 1) / 2^2 。常量折疊。等於(iNum + 3) / 4。除以4等於sar右移兩位。
對應的匯編代碼如下。
推薦本書籍:《C++反匯編與逆向分析技術揭秘》。
國內第一家從事軟件逆向工程師培訓的機構。http://www.51asm.com 強烈推薦!