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

矩陣乘法 C 程式反組譯全記錄:Debug/MaxSpeed/MinSize 三模式機器碼深度對比

     編輯:組合語言

以經典 3x3 矩陣乘法為例,在 VS2008 (x86) 環境下編譯,記錄 Debug(無優化)、Maximize Speed、Minimize Size 三種優化模式下的完整 x86 機器碼,展現編譯器如何從直譯源碼進化到指令級優化與程式碼壓縮。

原始 C 程式碼


void main() {
    int a[3][3]={{1,1,1},{2,2,2},{3,3,3}};
    int b[3][3]={{3,3,3},{2,2,2},{1,1,1}};
    int c[3][3];
    myfunction(a,b,c);
}
int myfunction(int a[3][3],int b[3][3],int c[3][3]) {
    int i,j;
    for(i=0;i<3;i++)
        for(j=0;j<3;j++)
            c[i][j]=a[i][0]*b[0][j]+a[i][1]*b[1][j]+a[i][2]*b[2][j];
    return 0;
}

模式一:Debug(無優化) - 源碼直譯

  • 完整堆疊框架(push ebp / mov ebp,esp),每個變數對應固定堆疊位移([ebp-XX])。
  • 陣列初始化逐元素 mov dword ptr [ebp-XX], value,佔用大量指令空間。
  • 迴圈計數器 i, j 存儲於堆疊,每次迴圈皆 mov/inc/cmp/jcc 往返記憶體。
  • 二維陣列索引計算:imul edx, edx, 0C (乘 12 bytes/列) + 固定位移 (0, 4, 8) 取元素。
  • 每次乘加結果存回堆疊,printf 參數壓堆疊呼叫。
  • 優點:除錯時指令與源碼行完美對應;缺點:指令多、記憶體存取頻繁、效能最差。

模式二:Maximize Speed - 寄存器重分配與指令重排

  • 省略 push ebp 框架(Leaf function 最佳化),直接用 sub esp, 8 保留少量堆疊空間。
  • 陣列初始化改用暫存器 mov eax,1/2/3 + mov [esp+offset], eax 批量寫入。
  • 關鍵優化:將陣列基址預先調整至內層迴圈所需起始位置(如 add eax, 0C 直接指向 b[1][0]),內層迴圈中以 esi 走訪陣列欄,edi 走訪列,ebx 指向結果陣列 c。
  • 大量運算在暫存器完成(imul, add),僅最終結果 mov [ebx], eax 寫入記憶體。
  • 迴圈計數器改用 ebp (i) 與 ebp (j) 遞減至零 (sub/jnz),消除 cmp 指令。
  • 指令流水線友善,指令數大幅減少,執行效率最高。

模式三:Minimize Size - 程式碼融合與 EBP 相對定址

  • 內聯:main 與 myfunction 合併為單一函數體,消除呼叫開銷。
  • 大量使用 EBP+位移 定址([ebp+ecx*4-34]),以單一基址覆蓋多個陣列,減少指令編碼長度。
  • 迴圈控制同樣採遞減計數,但指令編碼更緊湊(如 inc ebx 替代 add ebx,4)。
  • 犧牲部份速度(較多記憶體存取),換取最小機器碼體積。

對比總結表

維度DebugMaxSpeedMinSize
堆疊框架完整 EBP無/精簡完整 EBP
變數存放全堆疊暫存器為主堆疊+EBP相對
陣列存取乘法+固定位移預調基址+暫存器走訪EBP縮放索引定址
函數邊界獨立獨立內聯合併
指令數最多中等最少
適用場景除錯效能關鍵路徑嵌入式/啟動碼
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved