在没有 C 运行时的情况下与 VS2010 链接时出现无法解析的符号

发布于 2024-12-04 11:47:32 字数 2166 浏览 0 评论 0原文

我正在开发一个有大小限制的项目,因此我不想链接到 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 可以通过将#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
    }
}

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 #pragma check_stack(off) in front of the relevant functions. can be found in the CRT source that comes with Visual Studio.

_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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苄①跕圉湢 2024-12-11 11:47:32

以下是我必须从 VS2010 中的默认 Win32 项目进行更改的内容:

调试

  • C/C++ - 代码生成 - 基本运行时检查 = 默认
  • C/C++ - 代码生成 - 运行时库 = 多线程调试 (/MTd)
  • 链接器 - 输入 - 忽略特定默认库 = libcmtd.lib

发布

  • 常规 - 整个程序优化 = 无整个程序优化
  • C/C++ - 优化 - 整个程序优化 = 无
  • C/C++ - 代码生成 - 运行时库= 多线程 (/MT)
  • 链接器 - 输入 - 忽略特定默认库 = libcmt.lib

必须做更多事情来处理浮点内容:

  • C/C++ - 命令行 = /QIfist(也 SetFloatingPointRoundingToTruncate;请参阅下面的链接)
  • extern "C" int _fltused = 1; // 编译器定义的全局加载一些浮点内容

我遇到了一篇有趣的博客文章关于使用 VS 构建简约程序,我在其中找到了一些信息;如果您仍然遇到问题,可能会有其他提示。

通过所有这些调整,我能够编译和链接一个程序,将浮点数转换为 long 并调用一些 pow() 函数。发布版本只有 3.5 KB,其中包括嵌入式清单。

Here's what I had to change from a default Win32 project in VS2010:

Debug

  • C/C++ - Code Generation - Basic Runtime Checks = Default
  • C/C++ - Code Generation - Runtime Library = Multi-threaded Debug (/MTd)
  • Linker - Input - Ignore Specific Default Libraries = libcmtd.lib

Release

  • General - Whole Program Optimization = No Whole Program Optimization
  • C/C++ - Optimization - Whole Program Optimization = No
  • C/C++ - Code Generation - Runtime Library = Multi-threaded (/MT)
  • Linker - Input - Ignore Specific Default Libraries = libcmt.lib

Had to do a few more things to handle the floating point stuff:

  • C/C++ - Command Line = /QIfist (also SetFloatingPointRoundingToTruncate; see link below)
  • extern "C" int _fltused = 1; // a global the compiler defines to load some 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.

数理化全能战士 2024-12-11 11:47:32

我还参与过一个使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文