我正在处理一个有大小限制的项目,所以我不想链接Visual Studio的C运行时。我使用静态运行时(/ MT)和/ NODEFAULTLIB:LIBCMT标志执行此操作。我通过检查VS附带的运行时源来解决大部分问题。但是,编译器仍会生成一些未解析的外部符号:
_chkstk
:生成以检查大于4k的函数的堆栈。我可以关闭它或提供虚拟功能吗?
__libm_sse2_pow
和其他SSE调用:我可以通过关闭SSE代码生成来避免这些问题,但是如果可能的话我想拥有它们。这些符号似乎来自Intel lib(libmmd.lib?)。为什么这部分是C运行时呢?
_ftol2_sse
:将float转换为long。尽管关闭了SSE代码生成,我仍然得到了这个。
_CIpow
:另一个战俘功能。我想知道为什么编译器会生成这个而不是SEE。
是否有控制此代码生成的设置,预处理器宏或编译指示?我也尝试过使用visual studio 6.0 SP6中的msvcrt.lib,但我使用的一些函数不能与VS2010编译器一起使用。
修改
可以通过将_chkstk
放在相关函数前面来关闭 #pragma check_stack(off)
。可以在Visual Studio附带的CRT源代码中找到。
_CIpow
有点困难。它是pow的内在版本,它使用特殊的调用约定。我发现无法将其关闭,所以我最终在汇编程序中重新实现了它。我在这里得到了一些灵感:How to: pow(real, real) in x86。我有一段时间没有完成汇编程序,这是我第一次在x86上完成它。我没有为所有情况测试它,所以没有保证!如果您有任何改进建议或发现错误,请告诉我。
void __cdecl _CIpow(void)
{
// implementation of pow function as 2^(y*log2(x)). this is the
// intrinsic version so base and exponent are already on the fpu
// stack ST0 and ST1. the result is pushed to ST0.
// note that earlier rounding for fist was set to truncate
int temp;
__asm {
// values are repushed, cause fyl2x will overwrite them both
fld st(0) // push ST0 to ST0
fld st(2) // push ST2 (ex ST1) to ST0
fyl2x // ST1 = ST1*log2(ST0), pop ST0
fist temp // assumes truncate rouning
fisub temp // S0 = S0 - temp
f2xm1 // ST0 = (2^ST0)-1
fld1 // push 1 to ST0
faddp st(1),st(0) // ST1 = ST1 + ST0, pop ST0
fild temp // push temp to ST0
fxch // swap ST0 and ST1
fscale // ST0 = inc exp of ST0 by ST1
fxch // put reslut in ST1
fstp st(0) // pop ST0
}
}
答案 0 :(得分:3)
这是我必须从VS2010中的默认Win32项目更改的内容:
调试
推出
不得不做更多的事情来处理浮点数:
我遇到interesting blog post与VS建立极简主义程序的地方,在那里我找到了一些这样的信息;如果您仍有问题,可能会有其他提示。
通过所有这些调整,我能够编译和链接一个将float转换为long的程序并调用一些pow()函数。发布版本仅为3.5 KB,包括嵌入式清单。
答案 1 :(得分:2)
我还参与了一个用Visual Studio(.NET 2003)编译而不需要CRT的项目。更新版本的VS更难以使用,我们发现不值得让黑客使用它。
相反,您可能需要查看minicrt/lictiny。谷歌在奥马哈使用它 - 这是Chrome和谷歌地球的自动更新程序。
您可能还想尝试MinGW工具链,因为它可以链接到MSVCRT.DLL,它是一个系统组件,不需要由您的应用程序分发。