有没有其他方法可以解决这个问题?

时间:2015-08-14 23:06:10

标签: assembly x86

我开始学习装配,有人可以查看我的解决方案吗?

练习:

;您获得eax = a,ebx = b。计算(a ^ 3)* b + 5 *(b ^ 2),然后存储 结果在eax中。 (这里*表示乘法,c ^ d表示c d)的力量。

这是我的解决方案:

;Init the values
mov eax,3
mov ebx,2

;3,2 =>(3^3)*2 + 5*(2^2) = 27*2 + 5*4 = 54+20 = 74
;5,2 =>(5^3)*2 + 5*(2^2) = 125*2 + 5*4 = 250 + 20 = 270

;(a^3)*b 
mov esi,eax
mul eax
mul esi
mul ebx
;Store the value
mov esi,eax
;5*(b^2)
mov eax,ebx
mul ebx
mov ebx,5
mul ebx
;Calculate (a^3)*b + 5*(b^2)
lea eax,[esi + eax]

有没有办法用较少的指令解决这个问题? 谢谢大家。

1 个答案:

答案 0 :(得分:1)

号码是签名还是未签名? imul是整数(有符号)乘法,mul是无符号的。此外,2操作数imul r, rimul r32快,因为它不必计算产品的上半部分,或将其存储在任何地方。看起来你也可以使用2操作数形式保存很多mov指令。

总结评论:

乘以小常数因子为often best done with lea。您最多可以使用mov替换4条指令(包括lea),因为它可以为您提供非破坏性操作。 (目前不是其中一个来源)。

正如spyr03指出的那样,

a^3*b + 5*b^2 = b*(a^3 + 5*b)

你的最后指示:

lea eax,[esi + eax]

可能是一个简单的add eax, esi,它可以运行在比lea更多的执行端口上,因此它不太可能成为瓶颈的一部分。如果您不能使用另一条单指令执行等效操作,则只能使用lea。 (imul / mul除外。始终用lea替换。{/ p>

所以我可能会这样做:

mov  ecx, eax
imul ecx, eax            ; ecx = a^2
imul eax, ecx            ; eax = a^3
lea  edx, [ebx + 4*ebx]  ; edx = 5*b, ebx still = b
add  eax, edx            ; eax = a^3 + 5*b
imul eax, ebx            ; eax = b * (a^3 + 5*b)

始终评论您的asm代码。我喜欢这样的说法:asm代码只能有两种错误:代码与评论不匹配,或者评论没有描述执行任务的有效算法。

延迟:

  • 5*ba^3并行发生,速度更快(1个周期)。 (我把imul放在a之后,以确保CPU尽快开始处理较长的段链。)

  • 长dep链是涉及eax的那个。

    mov(1或0) - > imul(3) - > imul(3) - > add(1) - > IMUL(3) 总计= 10个周期

(在IvyBridge及更高版本中,reg-reg移动在寄存器重命名阶段完成,并且延迟为零。)

但是,它并不是很多指令,而且它们都是单指令,所以其他东西也有足够的空间与它并行发生。

即使以更多指令为代价,我也没有看到缩短依赖链的任何余地。 a^3*b5*b^2可以并行计算,并在最后添加,但在两个链的较长时间内仍然是3倍。