觀察各種運算式的求值過程
算術運算
1,包括“+,-,*,/”,如果不考慮編輯器的最佳化,他們在底層的運算過程一般是:先從記憶體中把值拷貝到寄存器中,然後在cpu中進行相應地運算,最後再把結果送回到記憶體。(對於常量一般就是直接當立即數用,都不需要經過記憶體)
註:’%’ 運算的符號和第一個運算元的符號一致。對於 ‘/’ 運算,有符號 / 有符號 = 有符號,無符號 / 無符號 = 無符號,但是要注意 有符號 / 無符號 這種混搭,是把有符號作無符號做處理的,即符號位當資料位元處理,所以這時結果是不正確的。至於如果兩個運算元都是整數那就是整除,有一個浮點數,那結果也是浮點類型。
2,自增和自減,有前自增(減)和後自增(減),在底層,其彙編操作是把它們拆分成兩部分進行的。例:a = 5 + (b++);就會等價a = 5 + b; b = b + 1;而a = 5 + (++b);就會等價 b = b + 1; a = 5 + b;
關係運算和邏輯運算
它們其實就是真與假的判斷,逆向分析時對它們具體的運算式並不關心。它們對應彙編中的條件跳轉指令。對於它們編譯器也有最佳化,如 ‘&&’ 第一個運算式為假,則結果為假,運算式二就不會執行了,’||’ 第一個運算式為真,則結果為真,運算式二同樣不會執行。還有三目的條件運算式,如果判斷是常量,則編譯器會直接知道取那個運算式的值,底層彙編就直接當一個普通運算式處理。
位元運算
這是一種無法復原的運算,所以像MD5這種密碼編譯演算法就是大量使用了位元運算。如x & 0 = 0;根據結果0是無法推出 x的。 編譯器使用的最佳化技巧
前言
就最佳化目的一般有下面這四個方向:(1)執行速度最佳化(2)記憶體儲存空間最佳化(3)磁碟儲存空間最佳化(4)編譯時間最佳化。而我們一般以執行速度最佳化為主。編譯器的工作過程:預先處理->詞法分析->文法分析->語義分析->中間代碼產生->目標代碼產生。其中,最佳化一般存在最後兩個階段。尤其中間代碼產生階段,這時還和具體硬體不相關,在不同硬體環境下可以通用。
與裝置無關的最佳化方案
1,常量摺疊
x = 1 + 2; –> x = 3;
2,常量傳播
接上例,y = x + 3; –>y = 6;
3,減少變數
x = i * 2;
y = j * 2;
if(x > y) –> if(i > j)
4,公用運算式
x = i * 2;
y = i * 2;
–>
x = i * 2;
y = x;
5,複寫傳播
x = a;
y = x + c;
–>
y = a + c;
6,剪去不可達分支
if(1 > 2)
{
…
}
–>這個語句會直接刪掉
7,順序語句代替分支
–>就是條件運算式所說的最佳化。
8,強度削落
用加法或移位代替乘法,用乘法或者移位代替除法。
9,數學變換
x = a + 0; –>x = a;
x = a * 1; –> x = a;
x = a * y + b * y; –> x = (a + b) * y;
10,代碼外提
while(x > y/2)
–>
t = y/2;
while(x > t)
與裝置相關的最佳化
1,流水線最佳化:就是同時能處理多條指令一起執行。
2,分支最佳化:…
3,快取(cache)最佳化:這個地區的訪問速度遠高於記憶體,所有常常把需要經常訪問的資料放這裡。