【问题标题】:What is the Lower and the higher part of multiplication in assembly instructions汇编指令中乘法的低位和高位是什么
【发布时间】:2018-10-23 04:13:20
【问题描述】:

我正在阅读this link,简而言之,有人可以向一周前开始学习汇编 x86 和 64 位的人解释当前 C++ 编译器的问题。

不幸的是,当前的编译器没有优化 @craigster0 的 nice 便携式版本,所以如果你想利用 64 位 CPU,你 不能使用它,除非作为没有#ifdef 的目标的后备 为了。 (我没有看到优化它的通用方法;您需要 128 位 类型或内在的。)

为了澄清,我正在研究汇编的好处,当我遇到人们在多篇文章中说当前的编译器在 64 位乘法方面没有优化,因为它们使用最低部分,所以它们没有执行完整64位乘法是什么意思。那么我在书中读到的更高部分的含义是什么?在 64 位架构中,只有最低 32 位用于 RFlags,这些相关的我很困惑吗?

【问题讨论】:

标签: c++ assembly


【解决方案1】:

大多数 CPU 允许您从两个操作数开始,每个操作数都有一个寄存器的大小,然后将它们相乘以获得填充两个寄存器的结果。

例如,在 x86 上,如果您将两个 32 位数字相乘,您将在 EDX 中获得结果的高 32 位,在 EAX 中获得结果的低 32 位。如果将两个 64 位数字相乘,则得到 RDX 和 RAX 的结果。

在其他处理器上,也使用其他寄存器,但基本原理相同:一个寄存器乘以一个寄存器得出的结果会填满两个寄存器。

C 和 C++ 没有提供利用该功能的简单方法。当您对小于int 的类型进行操作时,输入操作数将转换为int,然后将整数相乘,得到一个整数。如果输入大于 int,则将它们相乘为同一类型,结果为同一类型。没有考虑到结果是输入类型的两倍,实际上地球上的每个处理器都会产生两倍于每个输入单独的结果。

当然,有一些方法可以解决这个问题。最简单的是我们在小学学到的基本因式分解:取每个数字并将其分成上下两部分。然后我们可以将这些部分单独相乘:(a+b) * (c+d) = ac + ad + bc + bd。由于这些乘法中的每一个只有一半的非零位,我们可以将每个算术运算作为一个半大小的运算来产生一个完整的结果(加上一个从加法中执行的位)。例如,如果我们想在 64 位处理器上进行 64 位乘法以获得 128 位结果,我们会将每个 64 位输入分解为 32 位片段。然后每次乘法都会产生一个 64 位的结果。然后,我们将片段相加(通过适当的位移)以获得最终的 128 位结果。

但是,正如 Peter 指出的那样,当我们这样做时,编译器还不够聪明,无法实现我们想要完成的工作,并将乘法和加法序列转换回单个乘法,从而产生两倍大的结果每个输入。相反,它将表达式相当直接地转换为一系列乘法和加法,因此它所花费的时间大约是单次乘法的四倍。

【讨论】:

  • 公平地说... C 比支持它的处理器更老,因为它可以追溯到单个晶体管确实很昂贵的时间和地点。但这并不能成为以后不添加设施的借口。
  • @Mgetz:编译器通常会将a * (uint64_t)b 优化为单个mul 指令,用于unsigned a,b;,而不是实际执行零扩展然后3 次乘法/加法。问题在于利用超出最宽标准类型的范围。 (或者在问题中链接的帖子中,为了利用 64x64 => 128 乘法,因为没有 128 位宽度的可移植类型,并且 GNU C 仅在 64 位系统上提供 __int128,而不是在 32 位系统上这将需要更多的操作。)
  • @Mgetz:当时肯定有处理器完全没有乘法指令。至少据我所知,在大多数情况下,乘法指令产生的结果是输入的两倍。例如,IBM 360(可追溯到 1964 年)有一条 MR 指令,它在寄存器 T 和 T+1 中接受两个输入,并在相同的两个寄存器中产生结果。另一个明显的例外是一些专门用于浮点的机器(例如控制数据),它们只对浮点操作数进行乘法运算。
  • 公平地说,为乘法提供适当的支持会打破已经有些复杂的算术提升规则,他们需要添加整个“除乘法”子句,这也会使整个类型复杂化-大小关系 - 即 sizeof(char)
  • @SornelHaetir:要明确一点:这些都不是对 C 或 C++ 的攻击,只是指出它们是如何工作的。无论如何,我认为如果您真的愿意,提供支持会相当容易。一个明显的可能性是像template <class T> std::pair<T,T> dmul(T a, T b); 这样的库函数,它刚刚接收并返回了两个项目(是的,对于真实的东西,你需要添加一些std::make_unsigned<T> 等,但你明白了一般的想法)。或者,当然,只需添加一个任意精度的整数类。
猜你喜欢
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 2010-11-08
  • 2017-03-11
  • 2016-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多