如何在没有Standard C库的情况下使用编译器内置函数

时间:2014-12-12 16:54:06

标签: c++ c gcc optimization built-in

我知道某些功能,例如sin cos min max memcpy可能不会被视为正常功能,但可能被{{3}取代(当替换是(a)实际处理器指令时,这可能比仅仅内联函数调用更优化,例如在编译为标准FSIN函数时直接调用sin指令带有浮点单元的x86。)

我想使用内置函数的强大功能(在C / C ++中主要在mingw / gcc中可能是其他编译器),但我不想链接到l​​ibc,即标准C库。

  • 是否可以使用不链接到libc的内置?
  • 它们是否需要将这些符号优化为内置函数所需的命令行标志?

    (与之前相关,但重新定义)

  • 它们会被名称自动识别,还是启用内置插件所需的编译器标志?

2 个答案:

答案 0 :(得分:4)

@randomusername已经解释了许多常见标准C库函数的__builtin_前缀的用法。我建议使用#define进行更改,同时保持代码清洁。

#include <math.h>

#define  cos   __builtin_cos
#define  sin   __builtin_sin
#define  printf __builtin_printf

...
   printf("Distance is %f\n", cos(M_PI/4.0) * 7);
...

无标准C库

现在不使用标准C库,这意味着不链接到它,或包括典型的启动和退出代码存根,以及-nostdlib可能的GCC相当于-nostartfiles-nodefaultlibs

问题是您必须替换所有您通常使用的库函数,包括system calls(或来自glibc的wrappers /宏)以用于任何内核基础功能。

我不知道portable或强大的方法适用于处理器甚至necessarily不同的families(sysenter vs.syscall(指令)与int 0x80对于各种32位和64位x86处理器)。 ELF辅助矢量Elf32_auxv_t)和vDSO虚拟ELF动态共享对象)存在问题,可以解决和创建便携式解决方案,我不知道。

入口点

我相信所有GCC环境都使用相同的默认入口点,即标签/函数_start。这通常包含在&#34;启动文件&#34;然后调用传统的C / C ++入口点main。因此,您需要将其替换为您自己的最小存根(可以在C中)。

程序终止

我不知道如何以便携方式替换正确终止程序所需的_exit(rc)或类似功能。例如,在Linux环境中,它需要对内核函数SYS_exit进行系统调用(aka __NR_exitsys_exit

void _start(void) {
    int rc;
    /* Get command line arguments if necessary */
    rc = main(0, NULL);
    your_exit_replacement(rc);
}

替代

通常用户进程即应用程序,而不是操作系统内核或驱动程序,接受链接启动文件的开销和启用dynamic linking到Startard C库的必要开销因为内存被认为是便宜且容易获得的,对于任何真实的(实际上做某事)应用程序来说,节省内存是不值得的。在嵌入式域中,假设只有大量内存可用是不可接受的,另一种方法是使用最小的libc替换。对于Linux,有几个可用(例如musl,uClibc,dietlibc),我不知道是否有一个可用于mingw或Windows兼容的开源替换(ReactOS和Wine)。

另外

有关详细信息,从Linux平台的角度来看,Jessica McKellar在Oracle上发表了一篇很好的介绍"Hello from a libc-free world!" Part 1Part 2。还有一些相关的问题,在stackoverflow about using -nostdlib的各种情况下,有一些(部分情况下是部分)答案。

从这里开始取决于您的目标:教育,嵌入式,tiny program(Linux ELF可执行文件)或Windows PE executable竞赛。

Microsoft Windows

Microsoft Windows环境有各种文章处理.COM和.EXE可执行文件,以及Windows PE,但通常使用Microsoft的Visual Studio环境或程序集。经典&#34;经典&#34;是Matt Pietrek的Under the Hood专栏"Reduce EXE and DLL Size with LIBCTINY.LIB"(2001年1月出版的MSDN杂志)和"Remove Fatty Deposits from Your Applications Using Our 32-Bit Liposuction Tools"来自1996年10月的Microsoft Systems Journal。另一篇文章,但我还没有读过自己,似乎包括解释是"Reducing Executable Size"

答案 1 :(得分:2)

假设您要替换函数cos,您只需用代码cos替换代码中__builtin_cos的每一次出现。对于可以用编译器版本替换的任何其他函数也是如此。只需在名称前添加__builtin_

有关详细信息,请参阅gcc manual