gpt4 book ai didi

assembly - MUL/DIV 指令与 MOV & SHL/SHR (Pentium Pro)

转载 作者:行者123 更新时间:2023-12-02 19:52:20 26 4
gpt4 key购买 nike

您为什么要使用:

MOV EAX, 22 
SHL EAX, 2

...乘以 4 时而不是仅使用 MUL 指令?
据我所知,这也可以使用 SHR 而不是 DIV 来完成。

这样做有什么好处?
另外,你可以用奇数来做到这一点,还是只能用偶数?

最佳答案

有许多代码习惯用法比“MUL 常量”更快。

现代 x86 CPU 至少需要几个时钟来执行 MUL。因此,任何在 1-2 个时钟内计算乘积的代码序列都将优于 MUL。您可以使用快速指令(ADD、SHL、LEA、NEG),并且处理器可以在单个时钟内并行执行其中一些指令来取代 MUL。可以说,这意味着如果您避免某些数据依赖性,您可以在 2 个时钟内以多种组合执行其中 4 条指令。

LEA 指令特别有趣,因为它可以乘以一些小常数 (1,2,3,4,5,8,9),并将乘积移动到另一个寄存器,这是破坏数据的一种简单方法依赖关系。这使您可以在不破坏原始操作数的情况下计算子乘积。

一些例子:

将 EAX 乘以 5,将乘积移至 ESI:

   LEA ESI, [EAX+4*EAX]    ; this takes 1 clock

将 EAX 乘以 18:

   LEA  EAX, [EAX + 8*EAX]
SHL EAX, 1

将 EAX 乘以 7,将结果移至 EBX:

   LEA  EBX, [8*EAX]
SUB EBX, EAX

将 EAX 乘以 28:

   LEA  EBX, [8*EAX]
LEA ECX, [EAX+4*EAX] ; this and previous should be executed in parallel
LEA EAX, [EBX+4*ECX]

乘以 1020:

   LEA  ECX, [4*EAX]
SHL EAX, 10 ; this and previous instruction should be executed in parallel
SUB EAX, ECX

乘以 35

   LEA  ECX, [EAX+8*EAX]
NEG EAX ; = -EAX
LEA EAX, [EAX+ECX*4]

因此,当您想要实现乘以适度大小常数的效果时,您必须考虑如何将其“分解”为 LEA 指令可以生成的各种乘积,以及如何移位、添加、 或减去部分结果以获得最终答案。

通过这种方式可以产生多少乘以常数的结果,这是值得注意的。您可能认为这仅对非常小的常数有用,但正如您从上面的 1020 示例中看到的,您也可以获得一些令人惊讶的中等大小的常数。事实证明,这在对结构数组进行索引时非常方便,因为您必须将索引乘以结构的大小。通常,当对这样的数组进行索引时,您需要计算元素地址并获取值;在这种情况下,您可以将最终的 LEA 指令合并到 MOV 指令中,而真正的 MUL 则无法做到这一点。这会为您购买额外的时钟周期,以便通过这种类型的习惯用法来执行 MUL。

[我已经构建了一个编译器,通过对指令组合进行小型详尽的搜索,使用这些指令来计算“最佳乘以常数”;然后它会缓存该答案以供以后重用]。

关于assembly - MUL/DIV 指令与 MOV & SHL/SHR (Pentium Pro),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40952314/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com