比较宏和宏函数的工作效率

通过 gdb 查看程序的汇编代码,比较宏和宏函数的工作效率。

程序汇编代码

更精彩内容,可以关注我的博客:wenfh2020.com


程序

例子中的最大值实现,宏和函数逻辑基本相同。宏在源码预编译阶段,被替换为代码,增加了代码的体积;函数多了参数传递,函数进栈和出栈等逻辑,自然资源消耗要比宏多。

  • 测试代码
#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

汇编知识

测试中出现的汇编知识。

寄存器

寄存器描述
rbp64 bit 栈基址寄存器—指向栈底顶
ebp32 bit 栈基址寄存器—指向栈底
bp16 bit 栈基址寄存器—指向栈底
rsp64 bit 栈寄存器—指向栈顶
esp32 bit 栈寄存器—指向栈顶
sp16 bit 栈寄存器—指向栈顶
eax32 bit 通用寄存器
rip64 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位操作数


引用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值