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