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

程序重点:使用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而停止循环。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章