我正在阅读this link,总之有人可以向一周前开始学习汇编x86和64位的人解释当前C ++编译器的问题。
不幸的是,当前的编译器没有优化@ craigster0 便携式版本,因此,如果您想利用64位CPU,您可以 不能使用它,除非作为没有#ifdef的目标的备用 对于。 (我看不到优化它的通用方法;您需要一个128位 类型或内在类型。)
为澄清起见,我在研究汇编的好处时,我在多篇文章中遇到人们说,在编译64位乘法时,当前的编译器未进行优化,因为它们使用最低的部分,因此无法完全执行64位乘法意味着什么。那么获得较高部分的含义又是什么?我在书中读到,在64位架构中,只有最低的32位用于RFlags,这些相关的内容我感到困惑吗?
答案 0 :(得分:4)
大多数CPU将允许您从两个操作数开始,每个操作数的大小与一个寄存器的大小相同,然后将它们相乘得到一个填充两个寄存器的结果。
例如,在x86上,如果将两个32位数字相乘,则将在EDX中获得结果的高32位,而在EAX中获得结果的低32位。如果将两个64位数字相乘,则会得到RDX和RAX的结果。
在其他处理器上,使用了其他寄存器,但是应用了相同的基本思想:一个寄存器乘以一个寄存器得出的结果将填充两个寄存器。
C和C ++没有提供利用该功能的简便方法。当您对小于int
的类型进行操作时,输入操作数将转换为int
,然后将int相乘,结果为int。如果输入大于int,则将它们乘以相同的类型,结果是相同的类型。没有采取任何措施来考虑结果是输入类型的两倍大,并且实际上地球上的每个处理器都会产生的结果是单独输入的两倍。
当然,有一些处理方法。最简单的是我们在小学学习的基本因素:将每个数字分解为上下半部分。然后,我们可以将这些片段分别相乘:(a + b)*(c + d)= ac + ad + bc + bd。由于这些乘法中的每一个仅具有一半的非零位,因此我们可以将每个算术作为半尺寸运算来产生全尺寸结果(加上加法运算后得到的一位)。例如,如果我们想在64位处理器上进行64位乘法以获得128位结果,则可以将每个64位输入分解为32位。然后,每个乘法将产生64位结果。然后,我们将各个部分加在一起(并进行适当的移位)以得到最终的128位结果。
但是,正如Peter指出的那样,当我们这样做时,编译器不够聪明,无法意识到我们要完成的工作,并将乘法和加法序列转换为单个乘法,其结果是原来的两倍。每个输入。取而代之的是,它将表达式直接转换为一系列的乘法和加法运算,因此它所花费的时间大约是单次乘法的四倍。