我开始学习装配,有人可以查看我的解决方案吗?
练习:
;您获得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]
有没有办法用较少的指令解决这个问题? 谢谢大家。
答案 0 :(得分:1)
号码是签名还是未签名? imul
是整数(有符号)乘法,mul
是无符号的。此外,2操作数imul r, r
比imul 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*b
与a^3
并行发生,速度更快(1个周期)。 (我把imul
放在a
之后,以确保CPU尽快开始处理较长的段链。)
长dep链是涉及eax
的那个。
mov(1或0) - > imul(3) - > imul(3) - > add(1) - > IMUL(3) 总计= 10个周期
(在IvyBridge及更高版本中,reg-reg移动在寄存器重命名阶段完成,并且延迟为零。)
但是,它并不是很多指令,而且它们都是单指令,所以其他东西也有足够的空间与它并行发生。即使以更多指令为代价,我也没有看到缩短依赖链的任何余地。 a^3*b
和5*b^2
可以并行计算,并在最后添加,但在两个链的较长时间内仍然是3倍。