Assembly 有没有办法优化这个x86汇编代码?

Assembly 有没有办法优化这个x86汇编代码?,assembly,x86,Assembly,X86,假设在eax、ecx中给定了值。写一段代码 它计算5*eax+3*ecx+1,并将结果存储在eax中。(* 这里的意思是乘法) 我的代码: ;Initialize the values in eax and ecx mov eax,3 mov ecx,4 ;Compute 3*ecx mov ebx,eax mov eax,ecx mov edx,3 mul edx ; Compute 5*eax mov ecx,eax mov eax,ebx mov edx,5 mul edx ; Compu

假设在eax、ecx中给定了值。写一段代码 它计算5*eax+3*ecx+1,并将结果存储在eax中。(* 这里的意思是乘法)

我的代码:

;Initialize the values in eax and ecx
mov eax,3
mov ecx,4
;Compute 3*ecx
mov ebx,eax
mov eax,ecx
mov edx,3
mul edx
; Compute 5*eax
mov ecx,eax
mov eax,ebx
mov edx,5
mul edx
; Compute 5*eax + 3*ecx + 1
lea eax,[ecx + eax]
inc eax
如果“优化”是指优化指令计数,那么请使用
lea
甚至更多:

;Initialize the values in eax and ecx
mov eax,3
mov ecx,4

;Compute 3*ecx
lea ecx,[ecx*2 + ecx]

; Compute 5*eax
lea eax,[eax*4 + eax]

; Compute 5*eax + 3*ecx + 1
lea eax,[ecx + eax + 1]
这也是16字节的机器代码大小少,如果我的眼睛服务于我的权利

使用
lea
可以计算的规则列在指定偏移量的部分中。

如果“优化”是指对指令计数进行优化,那么请确保使用
lea
甚至更多:

;Initialize the values in eax and ecx
mov eax,3
mov ecx,4

;Compute 3*ecx
lea ecx,[ecx*2 + ecx]

; Compute 5*eax
lea eax,[eax*4 + eax]

; Compute 5*eax + 3*ecx + 1
lea eax,[ecx + eax + 1]
这也是16字节的机器代码大小少,如果我的眼睛服务于我的权利

使用
lea
可以计算的规则列在指定偏移量的部分中。

Michael(最优秀)的解决方案仍然可以稍微优化大小(短1字节),但这需要先进行一些代数操作

  5*eax + 3*ecx + 1
= 2*eax + 3*eax + 3*ecx + 1
= 2*eax + 3*(eax + ecx) + 1
这可以通过

(Excluding initialization of EAX and ECX)
add ecx, eax                  ; 2 bytes
lea ecx,[ecx*2 + ecx]         ; 3 bytes
lea eax,[eax*2 + ecx + 1]     ; 4 bytes
Michael的(最优秀的)解决方案仍然可以稍微优化大小(短1字节),但这首先需要一点代数操作

  5*eax + 3*ecx + 1
= 2*eax + 3*eax + 3*ecx + 1
= 2*eax + 3*(eax + ecx) + 1
这可以通过

(Excluding initialization of EAX and ECX)
add ecx, eax                  ; 2 bytes
lea ecx,[ecx*2 + ecx]         ; 3 bytes
lea eax,[eax*2 + ecx + 1]     ; 4 bytes

谢谢还有一个问题,我这样做错了吗?我的意思是,我应该专注于使用较少可能的指令来编写代码吗?如果你的目标是对代码进行速度优化或大小优化,那么就选择最好的指令来达到这个目标(注意:较少的指令并不一定意味着更小的机器代码或更快的代码)。否则,就用你觉得最容易理解的方式来写吧。我总是建议先让代码工作,然后再考虑在有意义的地方对其进行优化,这将取决于代码实际花费的大部分时间。经验告诉我,优化98%的代码非常容易,实际上不会影响大部分执行时间。:)谢谢还有一个问题,我这样做错了吗?我的意思是,我应该专注于使用较少可能的指令来编写代码吗?如果你的目标是对代码进行速度优化或大小优化,那么就选择最好的指令来达到这个目标(注意:较少的指令并不一定意味着更小的机器代码或更快的代码)。否则,就用你觉得最容易理解的方式来写吧。我总是建议先让代码工作,然后再考虑在有意义的地方对其进行优化,这将取决于代码实际花费的大部分时间。经验告诉我,优化98%的代码非常容易,实际上不会影响大部分执行时间。:)请注意,
imul
具有带有
imm8
arg的表单。当然,
lea
lea
add
方法会运行得更快。如果您的因素不适合使用
lea
,那将非常有用。(如果有符号乘法是可以的,并且您不需要结果的高32或高64。)此外,如果我确实需要无符号
mul
,我会先执行
eax
mul
来保存
mov
指令,然后将值移到一边。然后将
ecx
移动到
eax
以设置下一个
mul
。如果值不在regs中,您可以延迟加载第二个值。请注意,
imul
具有带有
imm8
arg的表单。当然,
lea
lea
add
方法会运行得更快。如果您的因素不适合使用
lea
,那将非常有用。(如果有符号乘法是可以的,并且您不需要结果的高32或高64。)此外,如果我确实需要无符号
mul
,我会先执行
eax
mul
来保存
mov
指令,然后将值移到一边。然后将
ecx
移动到
eax
以设置下一个
mul
。如果值不在regs中,您可以延迟加载第二个。很好,但是这会运行得更慢,因为只有一个线性依赖链。最近英特尔CPU上的复杂
LEA
指令以3周期延迟、1/周期吞吐量运行。(简单的
LEA
运行1c延迟,2/周期吞吐量。)如果您只需将
+1
作为LEA的一部分,并在末尾添加
,会怎么样?@PeterCordes-感谢您的速度分析。值得注意的是,优化大小和优化速度可以产生不同的代码。
lea-ecx,[ecx*2+ecx+1]/lea-eax,[eax*4+eax]/add-eax,ecx
与您的一样小,但这两个LEAs可以并行运行,因此,如果做更多的工作,您有时可以同时完成这两个任务。不过,我认为没有办法使用3组件寻址模式,这使得LEA的延迟为3个周期,而不是1个周期。(
eax*4+eax
仍然是1个周期;在英特尔SnB上,+1等于3个周期。)您的延迟应该是
1+1+3=5
延迟,但我的只有4个。我的另一个观点是,你不需要代数重排,只要把+1移到一个已经是LEA的op中就行了。很好,但是这会运行得更慢,因为只有一个线性依赖链。最近英特尔CPU上的复杂
LEA
指令以3周期延迟、1/周期吞吐量运行。(简单的
LEA
运行1c延迟,2/周期吞吐量。)如果您只需将
+1
作为LEA的一部分,并在末尾添加
,会怎么样?@PeterCordes-感谢您的速度分析。值得注意的是,优化大小和优化速度可以产生不同的代码。
lea-ecx,[ecx*2+ecx+1]/lea-eax,[eax*4+eax]/add-eax,ecx
与您的一样小,但这两个LEAs可以并行运行,因此,如果做更多的工作,您有时可以同时完成这两个任务。我看不到使用3-compo的方法