彙編條件判斷整理(JCC,CMP/TEST的實現)

比較的實現

咱們知道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指令表

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)

這裏有好多相等的指令(啊哈,這裏有一個有意思的現象,好多看似不沾邊的東西其實是相等的!),我猜是由於編譯器編譯起來就更方便了,不過作一個表也沒什麼難的,這個結論不成立啊……

這裏有一點要指出,無符號數用低於、高於來比較,而有符號數用大於、小於比較。

相關文章
相關標籤/搜索