| 模式 | 易失性 (呼叫端保存) | 非易失性 (被呼叫端保存) |
| 16-bit | AX, BX, CX, DX, SI, DI, ES, Flags (except DF) | CS, DS, SS, SP, BP |
| 32-bit | EAX, ECX, EDX, ESI, EDI | EBX, EBP, ESP, SS, CS, DS, ES, GS |
- 修改方向旗標 (DF) 必須恢復 (
cld/std)。
__fastcall 函數中避免使用 __asm 區塊(ECX/EDX 用於傳參,易衝突)。
- 區塊間不可假設暫存器保值,編譯器可能插入指令修改。
五、 流程控制與標號互跳
- C
goto label ↔ 組語 label: 互跳支援。
- 組語標號不分大小寫;C 標號分大小寫。
$ 代表當前位置:JNE $+5 跳過 5 位元組。
- 避免用函數名作標號(會跳至函數入口)。
六、 函數呼叫慣例
呼叫 C 函數 (cdecl, Caller Cleanup)
__asm {
push offset arg3
push offset arg2
push offset arg1
call printf
add esp, 12 ; 必須手動清理堆疊
}
呼叫 Windows API (stdcall, Callee Cleanup)
__asm {
push MB_OK
push offset szTitle
lea eax, szText
push eax
push 0
call DWORD PTR [MessageBoxA] ; 間接呼叫,避免重定位問題
}
返回值慣例
- 16-bit:
AX (16-bit), DX:AX (32-bit)
- 32-bit:
EAX (整數/指標/float), EDX:EAX (double, C linkage)
七、 實戰範例:高效率 CRC32 計算
完整 Win32 GUI 程式,輸入字串點擊按鈕顯示 CRC32。核心演算法以內嵌組語實現兩階段:
- 建表:256 入查找表,多項式
0xEDB88320(反轉形式)。
- 計算:逐位元組查表異或,全程暫存器運算(EAX=CRC, EBX=資料指標, ECX=長度, EDX=索引)。
; 建表
mov ecx, 256
_NextTable:
lea eax, [ecx-1]
push ecx
mov ecx, 8
_NextBit:
shr eax, 1
jnc _NotCarry
xor eax, 0xEDB88320
_NotCarry:
dec ecx
jnz _NextBit
pop ecx
mov [dwCRC32Table + ecx*4 - 4], eax
dec ecx
jnz _NextTable
; 計算
mov eax, -1
mov ebx, pbData
or ebx, ebx; jz _Done
mov ecx, nSize
or ecx, ecx; jz _Done
_NextByte:
mov dl, [ebx]
xor dl, al
movzx edx, dl
shr eax, 8
xor eax, [dwCRC32Table + edx*4]
inc ebx
loop _NextByte
_Done:
not eax
優勢:零堆疊存取、充分利用暫存器、loop 指令簡化迴圈、查表法避免逐位運算。效能遠超純 C 實作。
- 上一篇文章: 從組合語言視角理解程式語言本質
- 下一篇文章: Digital Mars C/C++ 內嵌組合語言權威指南(英文版完整收錄)
Copyright ©
程式碼之家 All Rights Reserved