比較宏和宏函數的工作效率

通過 gdb 查看程序的彙編代碼,比較宏和宏函數的工作效率。

程序彙編代碼


程序

例子中的最大值實現,宏和函數邏輯基本相同。宏在源碼預編譯階段,被替換爲代碼,增加了代碼的體積;函數多了參數傳遞,函數進棧和出棧等邏輯,自然資源消耗要比宏多。

  • 測試代碼
#define _max(x, y) (x) > (y) ? (x) : (y)

int max_func(int x, int y) {
    return x > y ? x : y;
}
int main() {
    int aaa, bbb, ccc, ddd, eee, mmm;

    aaa = 1;
    bbb = 2;
    eee = 3;
    mmm = 4;
    ccc = max_func(aaa, bbb);
    ddd = _max(aaa, bbb);
    eee = ddd;
}

預編譯後,宏被替換爲源碼。

gcc -E test.cpp -o test.i
int max_func(int x, int y) { return x > y ? x : y; }
int main() {
    int aaa, bbb, ccc, ddd, eee, mmm;

    aaa = 1;
    bbb = 2;
    eee = 3;
    mmm = 4;
    ccc = max_func(aaa, bbb);
    ddd = (aaa) > (bbb) ? (aaa) : (bbb);
    eee = ddd;
}

  • 編譯源碼爲 elf 文件進行 gdb 調試
gcc -g test.cpp -o test
  • 通過 gdb 命令查看程序彙編代碼
layout asm

0x4004ed <max_func(int, int)>           push   %rbp
0x4004ee <max_func(int, int)+1>         mov    %rsp,%rbp
0x4004f1 <max_func(int, int)+4>         mov    %edi,-0x4(%rbp)
0x4004f4 <max_func(int, int)+7>         mov    %esi,-0x8(%rbp)
0x4004f7 <max_func(int, int)+10>        mov    -0x4(%rbp),%eax
0x4004fa <max_func(int, int)+13>        cmp    -0x8(%rbp),%eax
0x4004fd <max_func(int, int)+16>        jle    0x400504 <max_func(int, int)+23>
0x4004ff <max_func(int, int)+18>        mov    -0x4(%rbp),%eax
0x400502 <max_func(int, int)+21>        jmp    0x400507 <max_func(int, int)+26>
0x400504 <max_func(int, int)+23>        mov    -0x8(%rbp),%eax
0x400507 <max_func(int, int)+26>        pop    %rbp
0x400508 <max_func(int, int)+27>        retq
0x400509 <main()>                       push   %rbp
0x40050a <main()+1>                     mov    %rsp,%rbp
0x40050d <main()+4>                     sub    $0x20,%rsp
0x400511 <main()+8>                     movl   $0x1,-0x4(%rbp)
0x400518 <main()+15>                    movl   $0x2,-0x8(%rbp)
0x40051f <main()+22>                    movl   $0x3,-0xc(%rbp)
0x400526 <main()+29>                    movl   $0x4,-0x10(%rbp)
0x40052d <main()+36>                    mov    -0x8(%rbp),%edx
0x400530 <main()+39>                    mov    -0x4(%rbp),%eax
0x400533 <main()+42>                    mov    %edx,%esi
0x400535 <main()+44>                    mov    %eax,%edi
0x400537 <main()+46>                    callq  0x4004ed <max_func(int, int)>
0x40053c <main()+51>                    mov    %eax,-0x14(%rbp)
0x40053f <main()+54>                    mov    -0x4(%rbp),%eax
0x400542 <main()+57>                    cmp    -0x8(%rbp),%eax
0x400545 <main()+60>                    jle    0x40054c <main()+67>
0x400547 <main()+62>                    mov    -0x4(%rbp),%eax
0x40054a <main()+65>                    jmp    0x40054f <main()+70>
0x40054c <main()+67>                    mov    -0x8(%rbp),%eax
0x40054f <main()+70>                    mov    %eax,-0x18(%rbp)
0x400552 <main()+73>                    mov    -0x18(%rbp),%eax
0x400555 <main()+76>                    mov    %eax,-0xc(%rbp)
0x400558 <main()+79>                    mov    $0x0,%eax
0x40055d <main()+84>                    leaveq
0x40055e <main()+85>                    retq

彙編知識

測試中出現的彙編知識。

寄存器

寄存器 描述
rbp 64 bit 棧基址寄存器—指向棧底頂
ebp 32 bit 棧基址寄存器—指向棧底
bp 16 bit 棧基址寄存器—指向棧底
rsp 64 bit 棧寄存器—指向棧頂
esp 32 bit 棧寄存器—指向棧頂
sp 16 bit 棧寄存器—指向棧頂
eax 32 bit 通用寄存器
rip 64 bit 地址偏移寄存器

彙編指令

命令 描述
jmp 無條件段內直接轉移指令
sub 減法指令
jle 條件轉移指令
mov 傳送指令
cmp 比較指令
push 進棧指令
pop 出棧指令
ret 段內過程返回指令,使子程序結束,繼續執行主程序
callq 相當於 pushq %rip; jmpq addr
leaveq 相當於 movq %rbp; %rsp popq %rbp
retq 相當於 popq %rip

callq,leaveq,retq 中的q是指64位操作數


引用

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章