您的位置:首页 > 其它

汇编-求数组中所有偶数的和

2016-04-19 20:58 246 查看
程序重点:使用test命令来判断一个数是不是偶数,而不是使用除2求余数。

使用除2求余数的方法太占寄存器了,设置被除数需要使用eax,设置除数需要一个寄存器,假定使用ebx,两者的商会存放到eax中,同时把余数存放到edx中。所以使用这种方法使用了三个寄存器。

而使用test这种方法就使得判断变得简单。

test des,src 的指令功能就是将des和src两个操作数进行与运算。

test与and指令是不同的,因为test指令不会改变des的值,它使得CF=OF=0,并改变ZF,SF标志的值。

我们的数值在计算机中存储为二进制,所以一个数的二进制表示最低位如果是1则该数为奇数,为0则为偶数。这一点通过二进制转换十进制公式也很好证明。

因此我们将要判断的数值与1进行test操作,如果是偶数则结果是0,通过判断ZF数值就可以判断是不是偶数。

下面是源程序:

;功能:求数组中所有偶数之和
;作者:王文堃
;创建时间:2016/4/19

INCLUDE vcIO.inc
.data
array DWORD 12,34,123,78,43,234,79,86,98,20
esum DWORD ? ;记录总和
str_output BYTE "数组中所有偶数的和为:%d",0ah,0
.code
main PROC
xor ebx, ebx ;使用寄存器存放总和,最后再赋值给esum以减少访存次数
mov edi, LENGTHOF array-1 ;edi记录数组最后一个数

jmp TESTING
;判断是不是偶数,若是则加入总和
DOLOOP:
test array[edi*4], 1
jnz NEXT
add ebx, array[edi*4]
NEXT:
dec edi

TESTING:
cmp edi, 0
jge DOLOOP
;编程要点,这里要使用有符号的大于等于跳转。
;如果使用无符号跳转jae则在递减的时候减到0之后还会减成全为F的最大数,陷入死循环。

;输出
mov esum, ebx
invoke printf, offset str_output, esum
ret
main ENDP
;子程序
END main


需要说明的是,为了减少寄存器的使用,我们使用了ecx倒着访问数组,判断条件是ecx大于等于0就循环。

但是一定要使用有符号数跳转jge,如果使用无符号跳转就会死循环。

下面解释一下为什么会死循环,其实原因也十分简单。

那无符号的八位数来说,它能表示的范围是0~255,如果将0-1结果就是255。所以当ecx减到0的时候,下一次再减1的时候它就为8个F的这样一个最大的数,它永远不可能因为ecx小于0而停止循环。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息