彙編-求數組中所有偶數的和

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

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