作者:alog
來源:http://ibf.tw/xqzCv
備註:如果作者不希望被轉帖到此處,請告知,小弟會馬上刪帖。
-------------------------------------------------------------------------------------
布林和比較指令 ( Boolean and Comparsion Instructions )
* CPU旗標
◆ 運算的結果為零,則設定 zero flag
◆ 運算結果所產生的目的運算元結果太大或太小(容器不夠裝),carry flag 會被設定
◆ Sign flag是目的運算元高位元的複製,被設定表示為負,被清除為正
◆ 指令產生無效的有號結果(al=+127, al+1爆 , al = -128 , al-1爆),over flag會被設定
◆ 運算結果造成目的運算元低位元裡其值為 1 的位元為偶數時,parity flag會被設定
* AND指令 : 兩運算元中每對相對應位元間的 and布林運算,結果存放目的運算元
AND 目的運算元 , 來源運算元
AND reg , reg
AND reg , mem
AND reg , imm
AND mem , reg
AND mem , imm
◆FLAGS : 總是清除 over及carry flag , 根據目的運算元的值修改 sign、zero、parity flags
◆常用來清除選定的位元並保持其它未被選擇位元不變
0 0 1 1 1 0 1 1
AND 0 0 0 0 1 1 1 1
----------------------------
0 0 0 0 1 0 1 1 ; 高四位元被清除,較低四位元保持不變
◆將字元轉換成大寫字母
01100001 = 61h('a')
and 11011111 = DFh ; 將字元與11011111作 and 運算轉成大寫
-----------------------------------
01000001 = 41h('A')
* OR指令 : 兩運算元中每對相對應位元間的 or 布林運算,結果存放目的運算元 OR 目的運算元 , 來源運算元
OR reg , reg
OR reg , mem
OR reg , imm
OR mem , reg
OR mem , imm
◆FLAGS : 同 and 指令
◆常用來設定被選擇位元並且保持其它未被選擇位元不變
0 0 1 1 1 0 1 1
OR 0 0 0 0 1 1 1 1
----------------------------
0 0 1 1 1 1 1 1 ; 高四位元不變,較低四位元被設定
◆將0~9整數位元組轉換成ASCII
00000101 = 05h
or 00110000 = 30h ; 將字元與00110000作 or 運算轉成ascii
-----------------------------------
00110101 = 35h('5')
* XOR指令 : 兩運算元中每對相對應位元間的 互斥 布林運算,結果存放目的運算元 XOR 目的運算元 , 來源運算元 ◆FLAGS : 同 and 指令
◆檢查同位旗標 : 按位元運算或算數運算結果的最低位元組其值為1的個數
偶數 => 偶同位,parity flag被設定
奇數 => 奇同位,parity flag被清除
將待測數全和零值作互斥能不改變待測數值,並完成同位檢查
mov al , 10110101b ; 5個1 => 奇同位
xor al , 0 ; 清除parity flag (PO)
mov al , 11001100b ; 4個1 => 偶同位
xor al , 0 ; 設定parity flag (PE)
* NOT指令 : 兩所有位元 0 變 1 ,1 變0,結果為 1 的補數
NOT reg
NOT mem ◆FLAGS : 不影響任何旗標
* TEST指令 : 兩運算元間每對相對應位元中 and 運算,依其結果設定旗標
和 and 唯一不同是不會修改目的運算元的值 常被用於「發現運算元個別的各個位元是否被設定」
00100101 ; 輸入值
00001001 ; test值,測試位元0和位元3
00000001 ; 結果 : ZF = 0
---------------------------------------------------
00100100 ; 輸入值
00001001 ; test值,測試位元0和位元3
00000000 ; 結果 : ZF = 1
◆FLAGS : 同 and 指令
* CMP指令 : 完成來源運算元和目的運算元間的減法,但不修改運算元的值
◆FLAGS : 同 sub 指令
CMP結果
|
ZF
|
CF
|
目的<來源
|
0
|
1
|
目的>來源
|
0
|
0
|
目的=來源
|
1
|
0
|
CMP結果
|
旗標
|
目的<來源
|
SF≠OF
|
目的>來源
|
SF=OF
|
目的=來源
|
ZF=1
|
* 清除或設定個別 CPU flag
◆方法 : ① 設定或清除 zero flag
and al , 0 ; 設定 zero flag,任何運算元和 0 作 and 運算
or al , 1 ; 清除 zero flag,.................. 1 .. or ........
② 設定或清除 sign flag
or al , 80h ; 設定 sign flag,運算元的最高位元和 1 作 or 運算
and al , 7Fh ; 清除 sign flag,.......................... 0 .. and ....
③ 設定或清除 carry flag
stc ; 設定 carry flag
clc ; 清除 carry flag
④ 設定或清除 overflow flag
將兩個正位元組值相加產生的和為負便能設定溢位旗標
若要清除可將一運元和 0 作 or 運算
mov al , 7Fh ; al = +127
inc al ; al = 80h(-128) , OF=1
or eax , 0 ; 清除 overflow flag
● 條件跳越 ( Conditional Jmps )
* 條件跳越指令的類型
跟據 ① 特殊的 flag 值
② 兩運算元是否相等或(E)AX的值
③ 無號運算元的比較
④ 帶正負號運算元間的比較
◆特殊的 flag 值
助憶符 | 說明 | 旗標 |
JZ | 若為零則跳 | ZF=1 |
JNZ | 若為不零則跳 | ZF=0 |
JC | 若進位則跳 | CF=1 |
JNC | 若不進位則跳 | CF=0 |
JO | 若溢位則跳 | OF=1 |
JNO | 若不溢位則跳 | OF=0 |
JS | 若負號則跳 | SF=1 |
JNS | 若非負號則跳 | SF=0 |
JP | 同位(偶)則跳 | PF=1 |
JNP | 非同位(奇)則跳 | PF=0 |
◆兩運算元是否相等或(E)AX的值
等式比較: CMP leftOp , rightOp
助憶符 | 說明 |
JE | 相等則跳(leftOp=rightOp) |
JNE | 不相等則跳(leftOp≠rightOp) |
JCXZ | 若 CX = 0 則跳 |
JECXZ | 若 ECX = 0 則跳 |
◆無號運算元的比較
助憶符 | 說明 |
JA | 較大則跳 |
JNBE | 不是較小或相等則跳(=JA) |
JAE | 較大或相等則跳 |
JNB | 不是較小則跳(=JAE) |
JB | 較小則跳 |
JNAE | 不是較大或相等則跳(=JB) |
JBE | 較小或相等則跳 |
JNA | 不是較大則跳(=JBE) |
◆ 帶正負號運算元間的比較
助憶符 | 說明 |
JG | 較大則跳 |
JNLE | 非較小或相等則跳(=JG) |
JGE | 較大或相等則跳 |
JNL | 不是較小則跳(=JGE) |
JL | 較小則跳 |
JNGE | 非較大或相等則跳(=JL) |
JLE | 較小或相等則跳 |
JNG | 不是較大則跳(=JLE) |
* 條件跳越的應用
①測試狀態位元 ; 第 0、1、4 位元其中之一被設定時進行跳越
mov al , status
test al , 00010011b ; 測試第0、1、4位元
jnz InputDataByte
; 第 2、3、7 位元全被設定時跳越,使用 and 和 cmp
mov al , status
and al , 10001100b ; 保留第2、3、7位元
cmp al , 10001100b ; 是否完全被設定
je ResetMachine ; 是則跳至標號所在
②兩數中較大者
mov dx , ax ; 假設 ax 較大
cmp ax , bx ; if ax >= bx 則
jae L1 ; 跳至L1
mov dx , bx ; 否則存 bx 值到 dx
L1: ; dx 包含較大的整數
③三整數中最小者
.data
V1 WORD ?
V2 WORD ?
V3 WORD ?
.code
mov ax , V1 ; 若 V1 最小
cmp ax , V2 ; if ax <= V2 則
jbe L1 ; 跳至 L1
mov ax , V2 ; 否則存 V2 值到 ax
L1: cmp ax , V3 ; 如果 ax <= V3 則
jbe L2 ; 跳至 L2
mov ax , V3 ; 否則存 V3 值到 ax
L2:
* 位元測試指令 : BT、BTC、BTR、BTS
①BT : 選擇其第一個運算元的第 n 位元並複製到進位旗標
BT bitBase , n
允許的運算元
BT r/m16 , r16
BT r/m32 , r32
BT r/m16 , imm8
BT r/m32 , imm8
; carry flag被指定為變數semaphore的第7位元
semaphore WORD 10001000b
BT semaphore , 7 ; CF = 1
②BTC : 選擇第一個運算元的第n位元複製到進位旗標並將第 n 位元反相
BTC bitBase , n
semaphore WORD 10001000b
BTC semaphore , 6 ; CF = 0 , semaphore = 11001000b
③BTR : 選擇第一個運算元的第n位元複製到進位旗標並清除第 n 位元
BTR bitBase , n
semaphore WORD 10001000b
BTR semaphore , 7 ; CF = 1 , semaphore = 00001000b
④BTS : 選擇第一個運算元的第n位元複製到進位旗標並設定第 n 位元 BTS bitBase , n
semaphore WORD 10001000b
BTS semaphore , 6 ; CF = 0 , semaphore = 11001000b
● 條件迴圈指令 ( Conditional Loop Instructions )
* LOOPZ和LOOPE指令
①LOOPZ : (loop if zero) zero flat 被設定和ecx的無號值>0允許迴圈繼續
目的標號的範圍需在其後指令的 -128 到 +127 bytes 之間
②LOOPE : 與LOOPZ同
◆執行邏輯: ecx = ecx -1 若 ecx > 0 且 ZF=1 ,則跳至目的
否則不進行跳越而繼續下一個指令
* LOOPNZ和LOOPNE指令
①LOOPNZ : (loop if not zero) 在ecx中的無號值>0且zero flag被清除時讓
迴圈繼續進行 ②LOOPNE : 與LOOPNZ同
◆執行邏輯: ecx = ecx -1 若 ecx > 0 且 ZF=0 ,則跳至目的
否則不進行跳越而繼續下一個指令
◆ 範例:掃描陣列中的每個元素直到發現一個正數(sign flag=0)
array SWORD -3 , -6 , -1 , -10 , 10 , 30 , 40 , 4
sentinel SWORD 0
mov esi , OFFSET array
mov ecx , LENGTHOF array
next:
test WORD PTR[esi] , 8000h ; test sign flag
pushfd ; 將flag放入堆疊
add esi , TYPE array
popfd ; 將flag從堆疊中拿出
loopnz next ; 迴圈繼續
jnz quit ; not found
sub esi , TYPE array ; esi 指向該值
quit:
● 條件結構 ( Conditional Structures )
* IF敘述
◆ 範例1 : if(op1 == op2) mov eax , op1 ; eax和op2作比較
{ cmp eax , op2 ;相等跳至L1
X=1; je L1 ;否則跳至L2
Y=2; jmp L2
} L1:
mov X,1
mov Y,2
L2:
-----------------------------------------------------------------------------
◆ 範例2 : clusterSize = 8192; mov clusterSize , 8192
if(gigabytes<8) cmp gigabytes , 8
clusterSize = 4096; jae next
mov clusterSize,4096
next:
* 複合運算式 高階 一般 簡化
◆ 範例 : if(a1>b1) AND (b1>c1) cmp al , bl ;第一個運算式 cmp al,bl
{ ja L1 jbe next
X = 1 ; jmp next cmp bl , cl
} L1: jbe next
cmp bl , cl ;第二個運算式 mov X,1
ja L2 next:
jmp next
L2: ; 皆為真
mov X,1 ; 將X設為1
next:
--------------------------------------------------------------------------------------------------------
*WHILE迴圈
◆ 範例1 : while(val1 < val2) mov eax , val1
{ while:
val1++; cmp eax , val2 ; val1<val2 ?
val2--; jnl endwhile ; 跳出迴圈
} inc eax ; val1++
dec val2 ; val2--
jmp while
endwhile:
mov val1,eax ; 新值存回val1
◆ 範例2: while(op1<op2) mov eax , op1 { mov ebx , op2
op1++; mov ecx , op3
if( op2 == op3) L1:cmp eax , ebx ; eax < ebx ?
X = 2; jl L2 ; 若成立
else jmp L7 ; 不成立
X = 3; L2: inc eax
} L3 : cmp ebx , ecx ; ebx == ecx?
je L4 ; 成立
jmp L5 ;不成立
L4 : mov X , 2 ; X=2
jmp L6
L5 : mov X , 3 ; X=3
L6 : jmp L1 ; 重複迴圈
沒有留言:
張貼留言