首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Visual C++ 內嵌組合語言完整參考:優缺點、語法、暫存器、呼叫慣例與 CRC32 實戰

     編輯:組合語言

MSVC 內嵌組譯器(__asm)讓 C/C++ 開發者無需外部工具鏈即可嵌入機器碼,適用於極致效能熱點、硬體存取、裝置驅動、naked 函數協定撰寫。本文系統整理官方文件精華,並附贈完整 CRC32 計算實戰範例。

一、 適用場景與限制

優點缺點/限制
無需獨立 MASM/Link 步驟不可攜(x86 專用,Alpha/ARM/ARM64 無法使用)
直接存取 C/C++ 變數/函數不支援 MASM 巨集、資料定義指令、結構/記錄
支援 486/Pentium/MMX 指令集編譯器不分析指令副作用,易破壞最佳化假設
原始碼級除錯 (/Zi, /FAs)不支援 64 位元模式 (x64 必須用獨立 .asm + ML64)

二、 __asm 區塊語法


__asm {
    mov eax, 1
    add eax, ebx
    ; 註解可用 ; 或 // 或 /* */
}
  • 區塊不影響 C 變數作用域,可巢狀。
  • 支援 EVEN/ALIGN 指令對齊。
  • _emit byte 偽指令替代 DB 定義單位元組(可構建機器碼/資料混雜區)。

三、 C/C++ 符號在組語中的使用

  • 變數名直接引用:mov eax, var。
  • 結構成員:mov ecx, [ebx]hal.same_name(非唯一需限定變數名)。
  • 陣列索引不自動縮放:array[6] = 位移 6 bytes。需手動 array[6 * TYPE int]。
  • 常數、enum、#define 巨集皆可用。
  • 不可呼叫 C++ 非靜態成員函數(thiscall 慣例複雜),可呼叫 extern "C" 全域函數。

四、 暫存器使用慣例(極重要)

  • 修改方向旗標 (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。核心演算法以內嵌組語實現兩階段:

  1. 建表:256 入查找表,多項式 0xEDB88320(反轉形式)。
  2. 計算:逐位元組查表異或,全程暫存器運算(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 實作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
模式易失性 (呼叫端保存)非易失性 (被呼叫端保存)
16-bitAX, BX, CX, DX, SI, DI, ES, Flags (except DF)CS, DS, SS, SP, BP
32-bitEAX, ECX, EDX, ESI, EDIEBX, EBP, ESP, SS, CS, DS, ES, GS