環境:Windows XP SP2 + VC6 + AMD Athlon 3000+。編寫 Ring0 驅動/測試代碼時,VC6 激進優化導致生成指令與預期不符,甚至破壞內聯組語語義。
// 關鍵結構定義
typedef struct _OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PUNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} OBJECT_ATTRIBUTES;
// 內聯組語進出 Ring0
#define ENTER_RING0 _asm pushad _asm pushfd _asm cli
#define LEAVE_RING0 _asm popfd _asm popad _asm retf
// 呼叫門描述符
typedef struct {
USHORT offset_0_15;
USHORT selector;
UCHAR param_count : 4;
UCHAR some_bits : 4;
UCHAR type : 4;
UCHAR app_system : 1;
UCHAR dpl : 2;
UCHAR present : 1;
USHORT offset_16_31;
} CALLGATE_DESCRIPTOR;
cli 與前後指令順序被調換,破壞中斷屏蔽時機;push/pop 序列被優化掉,導致堆疊不平衡;| 層級 | 方法 | 適用範圍 | 副作用 |
|---|---|---|---|
| 專案級 | 專案屬性 → C/C++ → Optimization → Disable (/Od) | 整個專案 | 效能大幅下降,調試友好 |
| 檔案級 | #pragma optimize("", off) ... #pragma optimize("", on) | 單一 .cpp | 局部關閉,粒度適中 |
| 函數級 | #pragma optimize("g", off) 函數前後 | 關鍵函數 | 僅關閉全域優化,保留局部 |
| 變數級 | 關鍵指標/暫存器映射變數加 volatile | 特定變數 | 防止讀寫被優化,不影響其他 |
| 組語級 | __asm { ... } 內使用 _emit 0x90 (NOP) 強制對齊/隔離 | 內聯組語塊 | 手工干預,極度靈活但易錯 |