咱們知道CMP是比較兩個寄存器內容的指令,但這是如何實現的?less
當執行到CMP指令的時候會讀取這兩個寄存器的內容,並加以減法運算,結果自己不保留,並按照結果設置符號位(屬算術運算)。測試
CMP是一個常常使用的指令,大多用來測試數字的大小。一個常見的例子spa
MOV EAX, 10 MOV EAX, 10 CMP EAX, EBX ;相減求出結果,爲0,將1存入ZF JE SOME_WHERE ;檢查ZF,爲1就跳 JNE SOME_WHERE ;檢查ZF,爲0就跳
當執行到TEST指令的時候會讀取這兩個寄存器的內容,並加以按位與運算,結果不保留,並按照結果設置符號位(屬邏輯運算)。code
TEST是一個用來檢測內容而不是運算內容的,常常用的一招是測試寄存器是否爲0:ci
TEST EAX, EAX JZ SOME_WHERE某個參考資料說
TEST EAX,EBX
與AND EAX,EBX
是同樣的,竊覺得不一樣,由於彙編的全部算術指令都是破壞性的,它會把結果存入 EAX,而TEST不會(就像C代碼a &= b;
)。若要 AND 也不會破壞原值,只能先入棧存值,而後在出棧前轉移結果,就像以下所示:編譯器MOV EAX, ?? ;賦值 MOV EBX, ?? PUSH EAX ;入棧保存EAX AND EAX, EBX ;運算 MOV EDX, EAX ;保存結果 POP EAX ;彈出恢復EAX可是你要本身作一個CMP指令是不切實際的,由於你本身仍是要判斷符號位的值,最終仍是用到了TEST, CMP這些指令。it
這些符號位存在一個叫作PSW(Program Status Word,程序狀態字)的16位(4字節)寄存器裏面。io
符號位 | 敘述 | 典型應用 |
OF | 溢出標誌,標明一個溢出的運算。真置1,假置0。 | 這個溢出,非溢出,我想我尚未弄懂 |
SF | 負號標誌,標明結果爲負數。真置1,假置0。 | int i = -100;asm if(i < 0)編譯 goto somewhere; |
ZF | 零標誌,標明結果爲0。真置1,假置0。 | 見上cmp例子 |
CF | 進位標誌,標明結果進位了。真置1,假置0。 | MOV EAX,1 MOV EBX,9 ADD EAX,EBX |
AF | 輔助進位標誌,記錄運算時第3位(半個字節)產生的進位。 | <null> |
PF | 奇偶標誌,結果操做數中1的個數爲偶置1(我猜是二進制下)。 | <null> |
DF | 方向標誌,在串處理指令中控制信息的方向(非運算) | (null) |
IF | 中斷標誌(非運算) | (null) |
TF | 陷井標誌(非運算) | (null) |
其中前幾個稱爲運算條件碼(condition code),後三個是邏輯控制標誌位,咱們在此對它們不感興趣。
JCC指條件跳轉指令,CC就是指條件碼。
JCC指令 | 中文含義 | 英文原意 | 檢查符號位 | 典型C應用 |
JZ/JE | 若爲0則跳轉; 若相等則跳轉 |
jump if zero; jump if equal |
ZF=1 | if (i == j); if (i == 0); |
JNZ/JNE | 若不爲0則跳轉; 若不相等則跳轉 |
jump if not zero; jump if not equal |
ZF=0 | if (i != j); if (i != 0); |
JS | 若爲負則跳轉 | jump if sign | SF=1 | if (i < 0); |
JNS | 若爲正則跳轉 | jump if not sign | SF=0 | if (i > 0); |
JP/JPE | 若1出現次數爲偶數則跳轉 | jump if Parity (Even) | PF=1 | (null) |
JNP/JPO | 若1出現次數爲奇數則跳轉 | jump if not parity (odd) | PF=0 | (null) |
JO | 若溢出則跳轉 | jump if overflow | OF=1 | (null) |
JNO | 若無溢出則跳轉 | jump if not overflow | OF=0 | (null) |
JC/JB/JNAE | 若進位則跳轉; 若低於則跳轉; 若不高於等於則跳轉 |
jump if carry; jump if below; jump if not above equal |
CF=1 | if (i < j); |
JNC/JNB/JAE | 若無進位則跳轉; 若不低於則跳轉; 若高於等於則跳轉; |
jump if not carry; jump if not below; jump if above equal |
CF=0 | if (i >= j); |
JBE/JNA | 若低於等於則跳轉; 若不高於則跳轉 |
jump if below equal; jump if not above |
ZF=1或CF=1 | if (i <= j); |
JNBE/JA | 若不低於等於則跳轉; 若高於則跳轉 |
jump if not below equal jump if abow |
ZF=0或CF=0 | if (i > j); |
JL/JNGE | 若小於則跳轉; 若不大於等於則跳轉 |
jump if less jump if not greater equal |
SF != OF | if (si < sj); |
JNL/JGE | 若不小於則跳轉; 若大於等於則跳轉; |
jump if not less; jump if greater equal |
SF = OF | if (si >= sj); |
JLE/JNG | 若小於等於則跳轉; 若不大於則跳轉 |
jump if less equal; jump if not greater |
ZF != OF 或 ZF=1 | if (si <= sj); |
JNLE/JG | 若不小於等於則跳轉; 若大於則跳轉 |
jump if not less equal jump if greater |
SF=0F 且 ZF=0 | if(si>sj) |
這裏有好多相等的指令(啊哈,這裏有一個有意思的現象,好多看似不沾邊的東西其實是相等的!),我猜是由於編譯器編譯起來就更方便了,不過作一個表也沒什麼難的,這個結論不成立啊……
這裏有一點要指出,無符號數用低於、高於來比較,而有符號數用大於、小於比較。