我正在尝试在不使用 C 运行时(msvcrt 或 libcmt)的情况下构建 Windows 控制台应用程序。那就是只链接 kernel32.lib 并使用来自 WIN32 API 的控制台函数而不是 printf 等。
我的问题是,在链接期间,编译器无法找到似乎可以处理 32 位应用程序中的 64 位整数除法的 __alldiv。我尝试了微软的编译器和英特尔的。
此函数存在于运行时库中。像 64 位整数这样基本的东西需要完整的 C 运行时,这很烦人。
任何想法如何克服这个问题?
找到了 __alldiv 链接问题的解决方案:
在 msdev 安装中找到lldiv.obj 。我可以将该对象文件添加到链接而不是 C 运行时。
对我来说,路径是:
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\crt\src\intel\mt_lib\lldiv.obj。
可以处理大于硬件除法器可以处理的除数的扩展精度除法例程比您想象的要复杂。我曾经不得不编写一个函数来将 128 个值除以 64 位值,这相当痛苦(在一般情况下很慢)。
看看 Randall Hyde 在他的“汇编语言艺术”文本(第 4 卷,第 4.2.5 节 - 扩展精度除法)中讨论的算法。
这是一段摘录:
您不能使用 DIV 和 IDIV 指令合成一般的 n 位/m 位除法运算。这样的操作必须使用一系列移位和减法指令来执行,并且非常混乱。但是,使用 DIV 指令可以轻松合成一个不太通用的操作,即 n 位数量除以 32 位数量。本节介绍了扩展精度除法的两种方法。
在描述如何执行多精度除法运算之前,您应该注意一些运算需要扩展精度除法,即使它们看起来可以使用单个 DIV 或 IDIV 指令计算。将 64 位数量除以 32 位数量很容易,只要得到的商适合 32 位。DIV 和 IDIV 指令将直接处理这个问题。但是,如果商不适合 32 位,那么您必须将此问题作为扩展精度除法来处理。这里的技巧是将被除数的(零或符号扩展的)HO dword 除以除数,然后用余数和被除数的 LO dword 重复该过程。
因此,您可能想要做的一件事是确定您是否真的需要在除数中使用 64 位数量 - 如果不需要,您可以轻松编写一个执行该任务的函数。如果你真的需要用 64 位值除以 64 位值,你仍然可以这样做,但这是一个更困难的问题。更具体地说,它可能不适合编译器“内联” - 因此它是一个库例程。
哦,别忘了——MS 提供了库源代码。 __alldiv()
是一个汇编语言函数lldiv.asm
。将该文件添加到您的项目中并在没有库的其余部分的情况下将其链接起来应该不会太难。
_alldiv的msdn页面说它的使用取决于编译器优化设置,但没有说明它所依赖的设置是什么。
Wine 中还有一个 _alldiv 你可以借用。