我知道某些功能,例如sin
cos
min
max
memcpy
可能不会被视为正常功能,但可能被{{3}取代(当替换是(a)实际处理器指令时,这可能比仅仅内联函数调用更优化,例如在编译为标准FSIN
函数时直接调用sin
指令带有浮点单元的x86。)
我想使用内置函数的强大功能(在C / C ++中主要在mingw / gcc中可能是其他编译器),但我不想链接到libc,即标准C库。
它们是否需要将这些符号优化为内置函数所需的命令行标志?
(与之前相关,但重新定义)
答案 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库,这意味着不链接到它,或包括典型的启动和退出代码存根,以及-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_exit
或sys_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 1和Part 2。还有一些相关的问题,在stackoverflow about using -nostdlib的各种情况下,有一些(部分情况下是部分)答案。
从这里开始取决于您的目标:教育,嵌入式,tiny program(Linux ELF可执行文件)或Windows PE executable竞赛。
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。