我有关于在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
这应该正常吗?如果是这样,有没有办法改善它?如果没有,实施有什么问题?
答案 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位。
总而言之: