使用帶有 Visual Studio 2022、除錯模式、X64 平臺的 Windows 10 Pro,我有以下代碼...
int main()
{
int var = 1;
int* varPtr = &var;
*varPtr = 10;
return 0;
}
在反匯編視窗中,我們看到了這個......
int var = 1;
00007FF75F1D1A0D C7 45 04 01 00 00 00 mov dword ptr [var],1
int* varPtr = &var;
00007FF75F1D1A14 48 8D 45 04 lea rax,[var]
00007FF75F1D1A18 48 89 45 28 mov qword ptr [varPtr],rax
*varPtr = 10;
00007FF75F1D1A1C 48 8B 45 28 mov rax,qword ptr [varPtr]
00007FF75F1D1A20 C7 00 0A 00 00 00 mov dword ptr [rax],0Ah
return 0;
在逐步執行上述操作后,RAX 暫存器將加載堆疊變數 var 的記憶體地址...
00007FF75F1D1A14 48 8D 45 04 lea rax,[var]
由于在此之后 RAX 沒有更改,為什么相同的 var 地址再次加載到 RAX 中,2 條指令后...
00007FF75F1D1A1C 48 8B 45 28 mov rax,qword ptr [varPtr]
記憶體視圖視窗顯示 &var 地址始終保持不變。我錯過了什么愚蠢的東西嗎?
[更新] - 切換到發布模式并關閉優化會完全回傳上述內容。打開速度/大小優化僅回傳“回傳 0”代碼。看看是否有一種方法可以強制編譯器編譯所有內容(使用快速開關)并強制它不洗掉它認為多余的東西,對于這個例子來說,這會很有趣。這個最小值似乎太小了,大聲笑。
仍然擔心 RAX 不必要的雙重負載 - 主要是對于這樣一個小程式,雖然是的,這就是“優化”的全部內容。窗臺。
uj5u.com熱心網友回復:
在除錯模式下編譯時(即禁用所有優化),編譯器生成這樣的代碼是有原因的。
假設您正在單步執行代碼并且您停在讀取*varPtr = 10;. 那時,您決定加載了錯誤的地址varPtr,并希望更改它并繼續除錯,而無需停止、重建和重新啟動程式。
好吧,在除錯模式下,你可以。只需更改存盤在varPtr(例如在 Watch 視窗中)的地址并進行除錯。如果沒有“冗余”的第二個負載,這將行不通。當編譯器發出所述負載時,它會發出。
因此,總而言之,除錯模式旨在使除錯更容易,而發布模式旨在使您的代碼盡可能快(或盡可能小)運行,并希望具有相同的語意。
并且感謝編譯器撰寫者理解這兩種操作模式的必要性。沒有它們,我們作為開發人員的生活將會更加艱難。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/411498.html
標籤:
上一篇:無法從庫的主檔案匯入特定匯出
