返回介绍

27 章 内联函数

发布于 2025-02-22 14:00:49 字数 2514 浏览 0 评论 0 收藏 0

内联代码是指当编译的时候,将函数体直接嵌入正确位置,而不是在这个位置放上函数声明。

#!cpp
#include <stdio.h>
int celsius_to_fahrenheit (int celsius)
{
    return celsius * 9 / 5 + 32;
};
int main(int argc, char *argv[])
{
    int celsius=atol(argv[1]);
    printf ("%d\n", celsius_to_fahrenheit (celsius));
};

这个编译是意料之中的,但是如果换成 GCC 的优化方案,我们会看到:

清单 27.2: GCC 4.8.1 -O3

#!bash
_main:
    push ebp
    mov ebp, esp
    and esp, -16
    sub esp, 16
    call ___main
    mov eax, DWORD PTR [ebp+12]
    mov eax, DWORD PTR [eax+4]
    mov DWORD PTR [esp], eax
    call _atol
    mov edx, 1717986919
    mov DWORD PTR [esp], OFFSET FLAT:LC2 ; "%d\12\0"
    lea ecx, [eax+eax*8]
    mov eax, ecx
    imul edx
    sar ecx, 31
    sar edx
    sub edx, ecx
    add edx, 32
    mov DWORD PTR [esp+4], edx
    call _printf
    leave
    ret

这里的除法由乘法完成。 是的,我们的小函数被放到了 printf() 调用之前。为什么?因为这比直接执行函数之前的“调用/返回”过程速度更快。 在过去,这样的函数在函数声明的时候必须被标记为“内联”。在现代,这样的函数会自动被编译器识别。 另外一个普通的自动优化的例子是内联字符串函数,比如 strcpy(),strcmp() 等

清单 27.3 : 另一个简单的例子

#!cpp
bool is_bool (char *s)
{
    if (strcmp (s, "true")==0)
    return true;
    if (strcmp (s, "false")==0)
    return false;
    assert(0);
};

清单 27.4: GCC 4.8.1 -O3

#!bash
_is_bool:
    push edi
    mov ecx, 5
    push esi
    mov edi, OFFSET FLAT:LC0 ; "true\0"
    sub esp, 20
    mov esi, DWORD PTR [esp+32]
    repz cmpsb
    je L3
    mov esi, DWORD PTR [esp+32]
    mov ecx, 6
    mov edi, OFFSET FLAT:LC1 ; "false\0"
    repz cmpsb
    seta cl
    setb dl
    xor eax, eax
    cmp cl, dl
    jne L8
    add esp, 20
    pop esi
    pop edi
    ret

这是一个经常可以见到的关于 MSVC 生成的 strcmp() 的例子。

清单 27.5: MSVC

#!bash
    mov dl, [eax]
    cmp dl, [ecx]
    jnz short loc_10027FA0
    test dl, dl
    jz short loc_10027F9C
    mov dl, [eax+1]
    cmp dl, [ecx+1]
    jnz short loc_10027FA0
    add eax, 2
    add ecx, 2
    test dl, dl
    jnz short loc_10027F80
    loc_10027F9C: ; CODE XREF: f1+448
    xor eax, eax
    jmp short loc_10027FA5
; ---------------------------------------------------------------------------
    loc_10027FA0: ; CODE XREF: f1+444
; f1+450
    sbb eax, eax
    sbb eax, 0FFFFFFFFh

我写了一个小的用于搜索和归纳的 IDA 脚本,这样的脚本经常能在内联代码中看到: https://github.com/yurichev/IDA_scripts.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文