在大会中循环

时间:2012-02-07 22:27:45

标签: assembly x86

我有关于在Assembly中循环的任务。没有什么困难,因为它只是课程的开始。我已经完成了所要求的工作,只是想知道我所做的是否正确。此外,我想知道是否有任何不需要或可以删除​​的东西。 (我喜欢看到不同的方式来处理事情,并能够看到什么更有效)。

Evaluate the sum of 2n - 5, where n goes from 1 to 7

这就是我所做的:

_num1
    DB    0

mov cx, 1    ; set counter to 1
mov eax, 0   ; use eax to keep total

eval:
    mov    [_num1], cx    ; set num1 to cx value
    shl    [_num1], 1     ; double value of num1
    add    eax, [_num1]   ; add values of 2n to eax
    sub    eax, 5         ; subtract 5 from eax (total)
    inc    cx             ; increment cx
    cmp    cx, 7          ; check if equal
    jne    eval

这应该正常吗?如果是这样,有没有办法改善它?如果没有,实施有什么问题?

1 个答案:

答案 0 :(得分:3)

通常一个人计算CX下降并循环直到CX达到零。有一个LOOP助记符,它可以在单个操作中完成。但是现在,在大多数CPU上,两个命令“dec cx; jnz”组合比LOOP快。仅在将代码大小优化到最后一位时才使用LOOP。

您可以使用DX寄存器代替使用内存引用(_num1),它在代码中未使用。寄存器比内存引用更快。

另一个常用的opimization是使用“xor eax,eax”而不是“mov eax,0”。 MOV会慢一些,因为它会将4个字节(0x00000000)从内存复制到寄存器。 XOR也将清除EAX寄存器,但不访问任何内存。它的代码也略小一些。

作为个人偏好,我会选择更高级别的评论。 “increment cx”对“inc cx”没有任何补充。我更喜欢评论每一行更高级别的语言,比如“eax = eax + 2 * ecx”。

更重要的是,您只为_num1保留了一个字节,但接着为其分配了两个字节(CX)。这将覆盖其他数据的一个字节。如果希望_num1保存两个字节,请使用“DW”而不是“DB”。另一个问题是混合操作数和不同大小的寄存器。如果你需要32位寄存器,请坚持下去。或者您可以在使用之前清除寄存器的高16位。或者您可以使用MOVZX助记符,它将在指定数据时清除高16位。

总而言之:

  • 从7倒数到1(使用LOOP或DEC ECX; JNZ)
  • 如果可能,使用寄存器代替内存引用
  • 使用XOR op注册零
  • 一些小错误