在 Win32 組語程式設計中,EBX、ESI、EDI 屬於「非易失性」(Non-volatile)或稱「被調用者保存」(Callee-saved)寄存器。根據 Microsoft 的呼叫慣例,被調用的函式若使用這些寄存器,必須在返回前將其恢復原值。然而,實際測試發現,在 Windows 2000 及更新版本的作業系統中,系統並不總是嚴格保護這些寄存器的值,這導致了一個經典的相容性陷阱。
若你的程式直接使用 EBX、ESI、EDI 而未先壓棧保存、用畢恢復,程式可能在 Windows 98 上運行正常,但在 Windows 2000、XP 或更高版本上卻會出現莫名其妙的「非法操作」或「存取違規」(Access Violation)。錯誤地址通常不在你的程式碼控制範圍內,極難除錯。
Windows 9x 系列核心較簡單,對寄存器上下文的切換處理較寬鬆;而 NT 核心(Win2000+)引入了更嚴格的執行緒上下文管理與 APC(非同步程序呼叫)機制。當系統進行執行緒切換、處理中斷或執行某些系統回呼時,若這些寄存器值被意外修改且未恢復,會導致核心或系統 DLL 的邏輯錯誤,進而觸發異常。
無論目標平台為何,組語程式設計師都應嚴格遵守 stdcall 慣例:
push 保存。pop 恢復。__asm 區塊中同樣適用此規則。MyFunction PROC
push ebx ; 保存非易失性寄存器
push esi
push edi
; ... 你的程式碼 ...
pop edi ; 逆序恢復
pop esi
pop ebx
ret
MyFunction ENDP
善用 USES 指令(MASM/TASM 支援)可自動產生保存/恢復代碼,減少人為疏漏:
MyFunction PROC USES ebx esi edi
; 直接使用寄存器,無需手動 push/pop
ret
MyFunction ENDP
養成良好的寄存器管理習慣,是編寫穩健、跨平台相容 Win32 組語程式的基石。