在没有 C 运行时的情况下与 VS2010 链接时出现无法解析的符号
我正在开发一个有大小限制的项目,因此我不想链接到 Visual Studio 的 C 运行时。我使用静态运行时 (/MT) 和 /NODEFAULTLIB:LIBCMT 标志来执行此操作。通过检查 VS 附带的运行时源代码,我已经解决了大部分问题。然而,编译器仍然生成一些无法解析的外部符号:
_chkstk
:生成用于检查大于 4k 的函数的堆栈。我可以关闭此功能或提供虚拟功能吗?
__libm_sse2_pow
和其他 SSE 调用:我可以通过关闭 SSE 代码生成来避免这些调用,但如果可能的话,我希望拥有它们。这些符号似乎来自英特尔库(libmmd.lib?)。为什么这部分是 C 运行时的一部分?
_ftol2_sse
:将 float 转换为 long。尽管关闭了 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
}
}
I'm working on a project with size restrictions, so I don't want to link against Visual Studio's C runtime. I do this with the Static Runtime (/MT), and the /NODEFAULTLIB:LIBCMT flags. I've got most things sorted out by checking the runtime sources that come with VS. However, the compiler still generates some unresolved external symbols:
_chkstk
: Generated to check the stack of a function larger than 4k. Can I turn this off or provide a dummy function?
__libm_sse2_pow
and other SSE calls: I can avoid these by turning off SSE code generation, but I'd like to have them if possible. These symbols seem to come from an Intel lib (libmmd.lib?). Why is this part of the C runtime anyway?
_ftol2_sse
: Convert float to long. I still get this despite turning off SSE code generation.
_CIpow
: Another pow function. I wonder why the compiler generates this instead of the SEE one.
Are there any settings, preprocessor macros or pragmas that control this code generation? I've also tried using msvcrt.lib from visual studio 6.0 SP6, but some functions I use are not working with the VS2010 compiler.
edit:
_chkstk
can be turned off by putting can be found in the CRT source that comes with Visual Studio.#pragma check_stack(off)
in front of the relevant functions.
_CIpow
was a little tougher. It's the intrinsic version of pow which uses a special calling convention. I found no way of turning it off so I ended up reimplementing it in assembler myself. I got some inspiration here: How to: pow(real, real) in x86. I haven't done assembler in a while and this is the first time I'm doing it on the x86. I didn't test it for all cases, so no guarantees! If you have any suggestions for improvement or find a bug, please let me know.
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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
以下是我必须从 VS2010 中的默认 Win32 项目进行更改的内容:
调试
发布
必须做更多事情来处理浮点内容:
我遇到了一篇有趣的博客文章关于使用 VS 构建简约程序,我在其中找到了一些信息;如果您仍然遇到问题,可能会有其他提示。
通过所有这些调整,我能够编译和链接一个程序,将浮点数转换为 long 并调用一些 pow() 函数。发布版本只有 3.5 KB,其中包括嵌入式清单。
Here's what I had to change from a default Win32 project in VS2010:
Debug
Release
Had to do a few more things to handle the floating point stuff:
I came across an interesting blog post on building minimalist programs with VS where I found some of this information; may have additional tips if you still have problems.
With all of these tweaks I am able to compile and link a program that casts a float to long and invokes some of the pow() functions. The release build is only 3.5 KB, and that includes the embedded manifest.
我还参与过一个使用 Visual Studio (.NET 2003) 编译而无需 CRT 的项目。 VS 的最新版本更难使用,我们发现不值得费尽心思让它工作。
相反,您可能想查看 minicrt/lictiny。谷歌在奥马哈使用这个 - Chrome 和 Google Earth 的自动更新程序。
您可能还想尝试 MinGW 工具链,因为它可以链接到 MSVCRT.DLL,这是一个系统组件,并且不不需要由您的应用程序分发。
I have also worked on a project that compiled with Visual Studio (.NET 2003) without requiring a CRT. More recent versions of VS were more difficult to use and we found it not worth the hacks to get it to work.
Instead you might want to look at minicrt/lictiny. Google use this in Omaha - the auto updater for Chrome and Google Earth.
You also might want to try the MinGW toolchain as this can link to MSVCRT.DLL which is a system component and doesn't need to be distributed by your application.