學習筆記-----淺談彙編指令CMP執行機制
在彙編中,CMP和JMP指令常常用於比較操作,而且檢視反彙編原始碼時也發現不管是.IF偽指令還是其他的底層都是用CMP實現的。
指令格式:
CMP 目的運算元,源運算元
計算機在遇到CMP指令的時候,CPU將目的運算元和源運算元做減法(即目的運算元-源運算元)從而根據運算結果修改標誌位(如OF, CF , ZF, SF等)的值,然後接下來用相應的跳轉指令來進行選擇執行哪一段程式碼
另外,運算元有無符號是個頭疼的事情,CPU並不能確定它運算的是有符號的減法還是無符號的減法,所以CPU會產生兩套標誌位。
由於我學的不是很深,下面只是簡單的討論一下CMP指令執行後標誌位的結果(有錯誤請指出)
ZF: 置零標誌位,當結果為0的時候ZF被賦值1
SF:負數標誌位,當結果是負數的時候被賦值1
CF:進位/借位標誌位,當最高位向它的上一位有借位或者進位的時候被賦值1
OF:溢位標誌位,當有益處時(即運算結果超過了它的型別(如BYTE, WORD, DWORD)所能表示的範圍)被賦值1
溢位的說明:兩個正數相加,兩個負數相加,正數減負數,負數減正數 都有可能溢位
正數溢位變負數,負數溢位變正數
1:無符號數的比較
目的運算元 < 源運算元ZF=0CF=1JB,JNAE
目的運算元 = 源運算元ZF=1CF=0JE,JZ
目的運算元 > 源運算元ZF=0CF=0JA,JNBE
2:有符號數的比較
目的運算元 < 源運算元ZF=0SF=1OF=0JL
ZF=0 SF=0OF=1
目的運算元 > 源運算元ZF=0SF=0OF=0JG
ZF=0 SF=1OF=1
目的運算元 = 源運算元ZF=1JE
另外在之前一直對CMP指令和之後的跳轉指令的順序模糊不清,現在也記錄一下
MOV EAX, 0
CMP EAX, VAL1
JBE FINISH
INC EAX
FINISH:
INC EAX
當比較EAX 和VAL1的值之後,
如果EAX <= VAL1 則跳轉到FINISH將EAX加1,最後EAX=1.
如果EAX > VAL1 則不跳轉 執行inc eax ,此時EAX=1, 隨後CPU並不是跳過FINISH語句塊,而是接著FINISH的語句繼續執行,所以還會執行一個INC EAX,最後EAX=2
想說明的一點就是CPU的指令時按順序一句一句執行的,除非遇到像JMP 或者CALL 之類的語句會實現跳轉。上述例子中EAX > VAL1時沒有實現跳轉,所以依舊是一步一步繼續執行。
所以如果想實現EAX和VAL1比較 大於則將eax賦值1,小於則不變,可以使用短路跳轉法
CMP EAX, VAL1
JBE FINISH
MOV EAX, 1
FINISH:
...........
如果想要用JA的話
CMP EAX, VAL1
JA Larger
JMP FINISH //此處需要告訴CPU跳過Larger語句 不執行大於時的操作
Larger:
MOV EAX,1
FINISH:
...........
就需要在JA跳轉後直接跳過Larger, 因為如果沒有JMP FINISH語句,當不滿足JA(即EAX > VAL1) CPU會繼續執行後面的語句Larger 所以最後不管EAX和VAL1的大小關係如何
EAX都被賦值1。