【问题标题】:80286: Which is the fastest way to multiply by 10?80286:乘以 10 的最快方法是什么?
【发布时间】:2020-07-16 21:02:05
【问题描述】:

若要将一个数乘以 2 的任意倍数,我会将其移位多次。

有没有这样的技术可以在更少的周期内将一个数字乘以 10?

【问题讨论】:

  • 特别是在 80286 上,所以可以立即移位,但是 imul reg,reg,10 很慢,而且像 lea ax, [eax + eax*4] 这样的 32 位寻址模式不适合便宜的 x * 5?您是否关心任何更新或早期 CPU 上的代码性能,以防 286 的最佳性能在其他地方不是最佳的?有 80286 指令时序的链接吗?
  • 移位、添加、移位? 10*x = (4*x + x) * 2 = ((x << 2) + x) << 1。这与您手动执行“长乘法”的方式相同。
  • 您将其保存在另一个寄存器中。 mov bx, ax ; shl ax, 2 ; add ax, bx ; shl ax, 1.
  • @ProjectZero:在 286 上,是的。即使在 P5 Pentium 上,用常数而不是 mul 进行移位/加法的阈值至少是几个设置位; 10 只有 2 个设置位。在现代 Nehalem 或更高版本上,是的优于 1 操作数 mul,但不优于 imul ax, bx, 10。 (3 个周期延迟,1/时钟吞吐量,1 uop)
  • 我不知道移位和加法的比较,但你也可以用四个加法来做:mov bx, ax ; add ax, ax ; add ax, ax ; add ax, bx ; add ax, ax

标签: assembly x86-16 micro-optimization


【解决方案1】:

80286 没有与 80386 一起引入的桶形移位器。根据 Microsoft Macro Assembler 5.0 文档 (1987) 中的时序表,SHL reg, immed8 需要 5+n 个周期,而 SHL reg, 1 需要 2 个周期。 ADD reg, reg 需要 2 个周期,MOV reg, reg 也是如此。 IMUL reg16, immed 需要 21 个周期。因此,乘以十的最快方法似乎是:

           ;       // cycles
shl ax, 1  ; *2    // 2
mov bx, ax ; *2    // 4
shl ax, 1  ; *4    // 6
shl ax, 1  ; *8    // 8
add ax, bx ; *10   // 10

或者,或者:

           ;      // cycles
mov bx, ax ; *1   // 2
shl ax, 1  ; *2   // 4
shl ax, 1  ; *4   // 6
add ax, bx ; *5   // 8
shl ax, 1  ; *10  // 10

十个循环。

【讨论】:

    猜你喜欢
    • 2016-02-06
    • 1970-01-01
    • 2011-04-08
    • 1970-01-01
    • 2018-03-09
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多