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

2022-07-04 13:51:14 字數 3785 閱讀 7666

我們知道cmp是比較兩個暫存器內容的指令,但這是如何實現的?

當執行到cmp指令的時候會讀取這兩個暫存器的內容,並加以減法運算,結果本身不保留,並按照結果設定符號位(屬算術運算)。

cmp是乙個經常使用的指令,大多用來測試數字的大小。乙個常見的例子

mov eax, 10

mov eax, 10

cmp eax, ebx ;相減求出結果,為0,將1存入zf

je some_where ;檢查zf,為1就跳

jne some_where ;檢查zf,為0就跳

當執行到test指令的時候會讀取這兩個暫存器的內容,並加以按位與運算,結果不保留,並按照結果設定符號位(屬邏輯運算)。

test是乙個用來檢測內容而不是運算內容的,經常用的一招是測試暫存器是否為0:

test eax, eax

jz some_where

某個參考資料說test eax,ebxand 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這些指令。

這些符號位存在乙個叫做psw(program status word,程式狀態字)的16位(4位元組)暫存器裡面。

符號位敘述

典型應用

of溢位標誌,標明乙個溢位的運算。真置1,假置0。

這個溢位,非溢位,我想我還沒有弄懂

sf負號標誌,標明結果為負數。真置1,假置0。

int i = -100;

if(i < 0)

goto somewhere;

zf零標誌,標明結果為0。真置1,假置0。

見上cmp例子

cf進製標誌,標明結果進製了。真置1,假置0。

mov eax,1

mov ebx,9

add eax,ebx

af輔助進製標誌,記錄運算時第3位(半個位元組)產生的進製。

pf奇偶標誌,結果運算元中1的個數為偶置1(我猜是二進位制下)。

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)

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

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

Linux C語言內聯彙編 條件跳轉

void jump 當sum的約束條件是 r 時,內聯彙編中應該初始化一下,movl 0,0 相當於初始化sum的中轉暫存器 比如下面,編譯器選擇 edx來暫存sum,如果不清零操作,其中的值是不確定的 再看看生成的.s檔案 subq 16,rsp movl 10,4 rbp movl 0,8 rb...

x86彙編 條件跳轉

條件跳轉表 直接轉移指令 指令格式 機器碼 測試標誌 條件說明 符號 jo opr 70of 1 結果有溢位 jno opr 71of 0 結果無溢位 jc opr 72cf 1 小於 jnc opr 73cf 0 大於或等於 jz je opr 74zf 1 結果為0 jnz jne opr 75...

shell if命令 判斷條件整理

語法結構 一行 if 1x ip x then echo abc fi 多行 if 1x ab x then echo you had enter ab elif 1x cd x then echo you had enter cd else echo you had enter unexpecte...