【发布时间】:2011-11-17 06:25:36
【问题描述】:
我正在处理一个有大小限制的项目,所以我不想链接到 Visual Studio 的 C 运行时。我使用静态运行时 (/MT) 和 /NODEFAULTLIB:LIBCMT 标志来执行此操作。通过检查 VS 附带的运行时源,我已经解决了大部分问题。但是,编译器仍然会生成一些未解析的外部符号:
_chkstk:生成检查大于 4k 的函数的堆栈。我可以关闭它或提供一个虚拟功能吗?
__libm_sse2_pow 和其他 SSE 调用:我可以通过关闭 SSE 代码生成来避免这些,但如果可能的话,我想拥有它们。这些符号似乎来自英特尔库(libmmd.lib?)。为什么这部分是 C 运行时的一部分?
_ftol2_sse: 将浮点数转换为长整数。尽管关闭了 SSE 代码生成,我仍然得到这个。
_CIpow: 另一个 pow 函数。我想知道为什么编译器会生成这个而不是 SEE 。
是否有控制此代码生成的任何设置、预处理器宏或编译指示?我也尝试过使用 Visual Studio 6.0 SP6 中的 msvcrt.lib,但我使用的一些函数不适用于 VS2010 编译器。
编辑:
_chkstk可以在相关函数前面加上可以在Visual Studio自带的CRT源码中找到。#pragma check_stack(off)来关闭。
_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
}
}
【问题讨论】:
-
您使用的是什么指令或功能?通过摆弄设置,我仍然可以使用 VS2010 构建一个“小”可执行文件。
-
@Luke:我不想重新分发 msvcrt100.dll。我可以通过链接系统的 msvcrt.dll(由于
tell()函数失败而无法工作)或链接到静态 msvcrt.lib 来避免这种情况,这会将可执行文件大小增加高达 200 KB。上面的符号是由简单的 float 到 long casts 和 math.h 函数生成的。
标签: c windows visual-studio linker code-generation