




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
看過破解教程,都知道test,cmp是比較關(guān)鍵,可是我一直不清楚它們究竟是怎么比較的,最后下決心找了很多資料,和大家一起把它們弄清楚.首先看看:狀態(tài)寄存器(即標(biāo)志寄存器)PSW(ProgramFlag)程序狀態(tài)字(即標(biāo)志)寄存器,是一個16位寄存器,由條件碼標(biāo)志(flag)和控制標(biāo)志構(gòu)成,
如下所示:1514131211109
8
7
6
5
4
3
2
1
0
OFDFIFTFSFZFAFPFCF條件碼:
①OF(OverflowFlag)溢出標(biāo)志,溢出時為1,否則置0.標(biāo)明一個溢出了的計算,如:結(jié)構(gòu)和目標(biāo)不匹配.
②SF(SignFlag)符號標(biāo)志,結(jié)果為負(fù)時置1,否則置0.
③ZF(ZeroFlag)零標(biāo)志,運算結(jié)果為0時置1,否則置0.
④CF(CarryFlag)進(jìn)位標(biāo)志,進(jìn)位時置1,否則置0.注意:Carry標(biāo)志中存放計算后最右的位.
⑤AF(AuxiliarycarryFlag)輔助進(jìn)位標(biāo)志,記錄運算時第3位(半個字節(jié))產(chǎn)生的進(jìn)位置。
有進(jìn)位時1,否則置0.
⑥PF(ParityFlag)奇偶標(biāo)志.結(jié)果操作數(shù)中1的個數(shù)為偶數(shù)時置1,否則置0.控制標(biāo)志位:
⑦DF(DirectionFlag)方向標(biāo)志,在串處理指令中控制信息的方向。
⑧IF(InterruptFlag)中斷標(biāo)志。
⑨TF(TrapFlag)陷井標(biāo)志。
為舉例方便說一下jnz和jz
測試條件
JZ
ZF=1
JNZ
ZF=0
即Jz=j(luò)umpifzero(結(jié)果為0則設(shè)置ZF零標(biāo)志為1,跳轉(zhuǎn))
Jnz=j(luò)umpifnotzero好,接著來看test和cmp*******************************************************************************
test屬于邏輯運算指令功能:執(zhí)行BIT與BIT之間的邏輯運算
測試(兩操作數(shù)作與運算,僅修改標(biāo)志位,不回送結(jié)果).
Test對兩個參數(shù)(目標(biāo),源)執(zhí)行AND邏輯操作,并根據(jù)結(jié)果設(shè)置標(biāo)志寄存器,結(jié)果本身不會保存。ESTAX,BX與ANDAX,BX命令有相同效果語法:TESTr/m,r/m/data
影響標(biāo)志:C,O,P,Z,S(其中C與O兩個標(biāo)志會被設(shè)為0)運用舉例:
1.Test用來測試一個位,例如寄存器:testeax,100b;
b后綴意為二進(jìn)制
jnz
******;
如果eax右數(shù)第三個位為1,jnz將會跳轉(zhuǎn)我是這樣想的,jnz跳轉(zhuǎn)的條件是ZF=0,ZF=0意味著ZF(零標(biāo)志)沒被置位,即邏輯與結(jié)果為1.2.Test的一個非常普遍的用法是用來測試一方寄存器是否為空:testecx,ecx
jzsomewhere如果ecx為零,設(shè)置ZF零標(biāo)志為1,Jz跳轉(zhuǎn)*******************************************************************************
CMP屬于算術(shù)運算指令功能:比較兩個值(寄存器,內(nèi)存,直接數(shù)值)
語法:CMPr/m,r/m/data
標(biāo)志位:C,P,A,Z,OCMP比較.(兩操作數(shù)作減法,僅修改標(biāo)志位,不回送結(jié)果).
cmp實際上是只設(shè)置標(biāo)志不保存結(jié)構(gòu)的減法,并設(shè)置Z-flag(零標(biāo)志).
零標(biāo)志很像carry,也是內(nèi)部標(biāo)志寄存器的一位.例如:
Cmpeax,2;
如果eax-2=0即eax=2就設(shè)置零標(biāo)志為1
Jz****;
如果設(shè)置了零標(biāo)志就跳轉(zhuǎn)
*******************************************************************************
我得出的結(jié)論
test邏輯與運算結(jié)果為零,就把ZF(零標(biāo)志)置1;
cmp算術(shù)減法運算結(jié)果為零,就把ZF(零標(biāo)志)置1.TEST
-
Test
For
Bit
Pattern
//位測試指令
Usage:
TEST
dest,src
//用法:TEST
dest,src
Modifies
flags:
CF
OF
PF
SF
ZF
(AF
undefined)
//受影響的標(biāo)志位有:
//你要注意的是這一部位才對。你上面的指令test
eax,eax后面跟著的是jnz指令,jnz指令作用于零標(biāo)志位的,若零標(biāo)志位不為零則跳,所以test
eax,eax是測試eax是否為零的指令,若eax有數(shù)據(jù),不管是什么數(shù)據(jù)(111也好,101也好),jnz都會跳。
//更新一下,若eax有數(shù)據(jù),不管是111也好,222也好,只要他們兩個操作數(shù)作邏輯與運算之后,結(jié)果不為零,則jnz都會跳。而jz則不跳。
CF
//進(jìn)位標(biāo)志,主要作用于JC/JNC指令。
OF
//溢出標(biāo)志,主要作用于JO/JNO指令
PF
//奇偶標(biāo)志,主要作用于JP/JPE/JNP/JPO指令
SF
//符號標(biāo)志,主要作用于JS/JNS指令
ZF
//零標(biāo)志,主要作用于JZ/JE/JNZ/JNE指令
AF
//輔助進(jìn)位標(biāo)志,不過未定義。
Performs
a
logical
AND
of
the
two
operands
updating
the
flags
//執(zhí)行兩個操作數(shù)的邏輯與運算,并更新標(biāo)志位。
register
without
saving
the
result.
//該操作只修改標(biāo)志位,不保留運算結(jié)果值。已經(jīng)有經(jīng)驗的知道TEST指令是對寄存器或者說對兩個操作數(shù)進(jìn)行邏輯與,然后影響標(biāo)志寄存器。
最常見的指令是TEST
EAX,EAX,
但是如何逆向出TEST指令呢?
對我們新手來說正向經(jīng)驗不足是個難度。
開始的時候
我也不知道從何下手得到這
TEST指令,
我就隨便看Object
Pascal官方中文版的書,
然后反出來看,
于是漸漸的TEST指令就出來了。
而實際要逆出的指令是這一組,
不妨我們都逆逆看。
0040899C
|.
8B1D
4CD24000
mov
ebx,
dword
ptr
[40D24C]
;
NoPacker.0040D164
004089A2
|.
8B5B
18
mov
ebx,
dword
ptr
[ebx+18]
004089A5
|.
85DB
test
ebx,
ebx
004089A7
|.
74
12
je
short
004089BB
004089A9
|.
A1
4CD24000
mov
eax,
dword
ptr
[40D24C]
004089AE
|.
E8
DDB9FFFF
call
<jmp.&kernel32.GetACP>
;
[GetACP
004089B3
|.
3BD8
cmp
ebx,
eax
004089B5
|.
0F85
D2030000
jnz
00408D8D
004089BB
|>
BA
9CE94000
mov
edx,
0040E99C
一、
(1)函數(shù)調(diào)用
00407CDC
|.
B8
FC7C4000
mov
eax,
00407CFC
;
ASCII
"0
:"
00407CE1
|.
E8
8AFFFFFF
call
00407C70
00407CE6
|.
B8
087D4000
mov
eax,
00407D08
;
ASCII
"Hello
World"
00407CEB
|.
E8
90FFFFFF
call
00407C80
(2)另外一種形式的
如
MessageBox(0,
PChar(varb),
PChar(varb2),
0);
00407CBF
|.
6A
00
push
0
00407CC1
|.
8B45
F8
mov
eax,
dword
ptr
[ebp-8]
00407CC4
|.
E8
77BCFFFF
call
00403940
00407CC9
|.
50
push
eax
00407CCA
|.
8B45
FC
mov
eax,
dword
ptr
[ebp-4]
00407CCD
|.
E8
6EBCFFFF
call
00403940
00407CD2
|.
50
push
eax
;
|Text
00407CD3
|.
6A
00
push
0
;
|hOwner
=
NULL
00407CD5
|.
E8
8EC8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
(3)兩個整型參數(shù)
func(90,
90);
00407D3A
|.
BA
5A000000
mov
edx,
5A
00407D3F
|.
B8
5A000000
mov
eax,
5A
00407D44
|.
E8
47FFFFFF
call
00407C90
(4)將兩個值相加再轉(zhuǎn)為string
tmpStr:=IntToStr(a
+
b);
00407CB8
|.
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
00407CBB
|.
8D041E
lea
eax,
dword
ptr
[esi+ebx]
00407CBE
|.
E8
01D6FFFF
call
004052C4
(5)值相加tBuf
:=
Integer('A');
tmpStr:=IntToStr(a
+
b
+
tBuf);
00407CB9
|.
BB
41000000
mov
ebx,
41
00407CBE
|.
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
00407CC1
|.
8D0437
lea
eax,
dword
ptr
[edi+esi]
00407CC4
|.
03C3
add
eax,
ebx
00407CC6
|.
E8
F9D5FFFF
call
004052C4
(6)獲取一個函數(shù)指針
00407CB9
|.
A1
A0974000
mov
eax,
dword
ptr
[4097A0]
00407CBE
|.
A3
9C974000
mov
dword
ptr
[40979C],
eax
(7)來回傳遞
F
:=
Func(P);
Func(P)
:=
F;
00407CB9
|.
A1
A0974000
mov
eax,
dword
ptr
[4097A0]
00407CBE
|.
A3
9C974000
mov
dword
ptr
[40979C],
eax
00407CC3
|.
A1
9C974000
mov
eax,
dword
ptr
[40979C]
00407CC8
|.
A3
A0974000
mov
dword
ptr
[4097A0],
eax
(8)
相同的反匯編結(jié)果
@F
:=
P;
和
F
:=
Func(P);
00407CB9
|.
A1
A0974000
mov
eax,
dword
ptr
[4097A0]
00407CBE
|.
A3
9C974000
mov
dword
ptr
[40979C],
eax
00407CCD
|.
A1
A0974000
mov
eax,
dword
ptr
[4097A0]
00407CD2
|.
A3
9C974000
mov
dword
ptr
[40979C],
eax
P
:=
@F;
和
Func(P)
:=
F;也是相同的
(9)調(diào)用
N
:=
F(N);
00407CDC
|.
A1
A4974000
mov
eax,
dword
ptr
[4097A4]
00407CE1
|.
FF15
9C974000
call
dword
ptr
[40979C]
00407CE7
|.
A3
A4974000
mov
dword
ptr
[4097A4],
eax
(10)
N
:=
Func(P)(N);
00407CEC
|.
A1
A4974000
mov
eax,
dword
ptr
[4097A4]
00407CF1
|.
FF15
A0974000
call
dword
ptr
[4097A0]
00407CF7
|.
A3
A4974000
mov
dword
ptr
[4097A4],
eax
(11)
00407CB9
|.
BB
03000000
mov
ebx,
3
;
I
:=
3
00407CBE
|.
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
;得到tmpStr地址
00407CC1
|.
8D0437
lea
eax,
dword
ptr
[edi+esi]
;edi+esi就是90+90
00407CC4
|.
03C3
add
eax,
ebx
;
I
+
edi
+
esi值
00407CC6
|.
E8
F9D5FFFF
call
004052C4
;
存儲在tmpStr內(nèi)
(12)
00407CB9
|.
BB
03000000
mov
ebx,
3
;I
:=
3
00407CBE
|.
43
inc
ebx
;I
:=
I+1;
(13)當(dāng)不自動為變量初始化時Delphi會自己給變量初始化,
形態(tài)是這樣的。
//一般不是自己手動的臨時變量要么是作為輸入?yún)?shù)要么是作為中轉(zhuǎn)存儲。
00407C9B
|.
894D
F8
mov
dword
ptr
[ebp-8],
ecx
00407C9E
|.
894D
F4
mov
dword
ptr
[ebp-C],
ecx
00407CA1
|.
8955
FC
mov
dword
ptr
[ebp-4],
edx
(14)Delphi的臨時??臻g是在每個函數(shù)的后面。
00407D1F
00
db
00
00407D20
.
FFFFFFFF
dd
FFFFFFFF
00407D24
.
14000000
dd
00000014
00407D28
.
4D
69
63
72
6F
73
>ascii
"Microsoft
vs
Bor"
00407D38
.
6C
61
6E
64
00
ascii
"land",0
00407D3D
00
db
00
00407D3E
00
db
00
00407D3F
00
db
00
如這段,
它在00407D1F之前存在一個函數(shù)將引用此段內(nèi)某臨時變量。
(15)
一個邏輯表達(dá)式
Done
:=
(I>=1)
and
(I<100);
00407CB6
|.
83FB
01
cmp
ebx,
1
(1)
00407CB9
|.
7C
05
jl
short
00407CC0
00407CBB
|.
83FB
64
cmp
ebx,
64
(100)
00407CBE
|.
7C
04
jl
short
00407CC4
00407CC0
|>
33C0
xor
eax,
eax
//清零
00407CC2
|.
EB
02
jmp
short
00407CC6
00407CC4
|>
B0
01
mov
al,
1
//清1
00407CC6
|>
8BD8
mov
ebx,
eax
(16)
sqr求平方,
sqrt開平方
I:=
Sqr(J);
00407CB3
|.
B9
64000000
mov
ecx,
64
00407CB8
|.
8BC1
mov
eax,
ecx
00407CBA
|.
F7E8
imul
eax
00407CBC
|.
8BD8
mov
ebx,
eax
(17)關(guān)鍵字
test終于被我再次搞出來了,
且是存在于循環(huán)之中。
00407CB3
|.
BB
64000000
mov
ebx,
64
00407CB8
|>
4B
/dec
ebx
00407CB9
|.
85DB
|test
ebx,
ebx
//這里的test
ebx
ebx正好合乎我的需求。
00407CBB
|.^
7F
FB
\jg
short
00407CB8
當(dāng)然肯定還有各種test的情形,
不一定非要是循環(huán)。不過我們到是可以檢測下各種
條件表達(dá)式下的循環(huán)。
[源]
I
:=
100;
while
I
>
0
do
begin
I:=
I-1;
end;
關(guān)于條件表達(dá)式中進(jìn)行總結(jié)。
根據(jù)上面的循環(huán)由于
I
和
0
作比較,
所以一般用test指令作為檢測指令。然后根據(jù)
標(biāo)志寄存器狀態(tài)作跳轉(zhuǎn)。我根據(jù)此推測又寫了一個循環(huán),同樣還是讓另外一個新變量J和
0作比較。
[反]
00407CB3
|.
BB
64000000
mov
ebx,
64
;i
=
100
00407CB8
|.
B8
04000000
mov
eax,
4
;j
=
4;
00407CBD
|>
48
/dec
eax
;循環(huán)四次,沒次減1
00407CBE
|.
85C0
|test
eax,
eax
00407CC0
|.^
75
FB
\jnz
short
00407CBD
00407CC2
|.
85DB
test
ebx,
ebx
00407CC4
|.
7E
05
jle
short
00407CCB
;(test后若ZF!=OF或ZF=1)轉(zhuǎn)
;否則循環(huán)100次,每次減1
00407CC6
|>
4B
/dec
ebx
00407CC7
|.
85DB
|test
ebx,
ebx
00407CC9
|.^
7F
FB
\jg
short
00407CC6
00407CCB
|>
\8D55
FC
lea
edx,
dword
ptr
[ebp-4]
這是根據(jù)循環(huán),我目的是想產(chǎn)生類似這樣的代碼。
0040899C
|.
8B1D
4CD24000
mov
ebx,
dword
ptr
[40D24C]
;
NoPacker.0040D164
004089A2
|.
8B5B
18
mov
ebx,
dword
ptr
[ebx+18]
004089A5
|.
85DB
test
ebx,
ebx
004089A7
|.
74
12
je
short
004089BB
004089A9
|.
A1
4CD24000
mov
eax,
dword
ptr
[40D24C]
004089AE
|.
E8
DDB9FFFF
call
<jmp.&kernel32.GetACP>
;
[GetACP
004089B3
|.
3BD8
cmp
ebx,
eax
004089B5
|.
0F85
D2030000
jnz
00408D8D
004089BB
|>
BA
9CE94000
mov
edx,
0040E99C
現(xiàn)在知道了如何產(chǎn)生
test指令,
而cmp指令則很容易產(chǎn)生,一般
邏輯或條件表達(dá)式
內(nèi)又大于0的數(shù)就會使用cmp作減法,
然后比較,
test
和
cmp都是
將兩個操作數(shù)進(jìn)行
邏輯和算術(shù)運算,但是不修改寄存器值。
test負(fù)責(zé)邏輯判斷影響標(biāo)志寄存器。
cmp進(jìn)行算術(shù)寄存器,也影響標(biāo)志寄存器。
現(xiàn)在再次推理,
如果被比較的操作數(shù)是小于0,
或者
是個存儲器操作數(shù),或是個函數(shù),
或是其他形式
該如何產(chǎn)生test指令呢?
如果
被比較的數(shù)是1或
-1會不會也產(chǎn)生
test指令呢。
下面這段是前面兩個小循環(huán)
I
:=
100;
J
:=
4;
while
j
<>
0
do
begin;
J
:=
J
-
1;
end;
while
I
>
0
do
begin
I:=
I-1;
end;
//先面開始測試是否
跟
1
-1等有關(guān),
也可產(chǎn)生test指令。
第一次試驗失敗,看來跟1比較是不行的
00407CB3
|.
B8
64000000
mov
eax,
64
00407CB8
|>
48
/dec
eax
00407CB9
|.
83F8
01
|cmp
eax,
1
00407CBC
|.^
75
FA
\jnz
short
00407CB8
[源]
J
:=
100;
while
j
<>
1
do
begin;
J
:=
J
-
1;
end;
還有-1
同樣也失敗
00407CB3
|.
B8
64000000
mov
eax,
64
00407CB8
|>
48
/dec
eax
00407CB9
|.
83F8
FF
|cmp
eax,
-1
00407CBC
|.^
75
FA
\jnz
short
00407CB8
[源]
J
:=
100;
while
j
<>
1
do
begin;
J
:=
J
-
1;
end;
看來都不行,
不過現(xiàn)在知道和0比較可以了就可以了。那么再次推測,和常量0
或者
存儲器0,
或者其他形式的,
如返回值0比較是否也要產(chǎn)生test指令呢?
先不管循環(huán)的形式,
如果將條件轉(zhuǎn)移為if
then
else
...類的條件內(nèi)和0比較是否也可以呢
00407CB3
|.
B8
64000000
mov
eax,
64
00407CB8
|.
85C0
test
eax,
eax
00407CBA
|.
7E
13
jle
short
00407CCF
00407CBC
|.
6A
00
push
0
;
/Style
=
MB_OK|MB_APPLMODAL
00407CBE
|.
68
3C7D4000
push
00407D3C
;
|Title
=
"Hello
World"
00407CC3
|.
68
3C7D4000
push
00407D3C
;
|Text
=
"Hello
World"
00407CC8
|.
6A
00
push
0
;
|hOwner
=
NULL
00407CCA
|.
E8
99C8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
00407CCF
|>
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
看來是可以的,
[源]
J
:=
100;
if
J
>
0
then
begin
MessageBox(0,
'Hello
World',
'Hello
World',
0);
end;
小結(jié):
test是兩兩個寄存器作與運算,然后影響標(biāo)志寄存器,然后后面的轉(zhuǎn)移指令根據(jù)標(biāo)志寄存器
來轉(zhuǎn)。
我稍微改變了個符號后
00407CB3
|.
B8
64000000
mov
eax,
64
00407CB8
|.
85C0
test
eax,
eax
00407CBA
|.
7D
13
jge
short
00407CCF
00407CBC
|.
6A
00
push
0
;
/Style
=
MB_OK|MB_APPLMODAL
00407CBE
|.
68
3C7D4000
push
00407D3C
;
|Title
=
"Hello
World"
00407CC3
|.
68
3C7D4000
push
00407D3C
;
|Text
=
"Hello
World"
00407CC8
|.
6A
00
push
0
;
|hOwner
=
NULL
00407CCA
|.
E8
99C8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
[源]
J
:=
100;
if
J
<
0
then
begin
MessageBox(0,
'Hello
World',
'Hello
World',
0);
end;
則jle
被改為了jge,
jge要求
SF=OF,
由于test指令對eax進(jìn)行了與運算,將全部標(biāo)志寄存器清零了。
所以SF=OF,所以要轉(zhuǎn)。好下面完成后面的測試,
當(dāng)被比較的不是0,
是常量,是變量,是函數(shù)時
會產(chǎn)生什么代碼。
(1).1常量
[源]
const
ZeroN
=
0;
...
J
:=
100;
if
J
<
ZeroN
then
begin
MessageBox(0,
'Hello
World',
'Hello
World',
0);
end;
[反]
00407CB3
|.
B8
64000000
mov
eax,
64
00407CB8
|.
85C0
test
eax,
eax
00407CBA
|.
7D
13
jge
short
00407CCF
00407CBC
|.
6A
00
push
0
;
/Style
=
MB_OK|MB_APPLMODAL
00407CBE
|.
68
3C7D4000
push
00407D3C
;
|Title
=
"Hello
World"
00407CC3
|.
68
3C7D4000
push
00407D3C
;
|Text
=
"Hello
World"
00407CC8
|.
6A
00
push
0
;
|hOwner
=
NULL
00407CCA
|.
E8
99C8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
00407CCF
|>
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
看來常量是可以的。那么存儲器的呢。
存儲器的就不行了
00407CB3
|.
B8
64000000
mov
eax,
64
;J
:=
100;
00407CB8
|.
33DB
xor
ebx,
ebx
;I
:=
0;
00407CBA
|.
3BD8
cmp
ebx,
eax
00407CBC
|.
7E
13
jle
short
00407CD1
00407CBE
|.
6A
00
push
0
;
/Style
=
MB_OK|MB_APPLMODAL
00407CC0
|.
68
407D4000
push
00407D40
;
|Title
=
"Hello
World"
00407CC5
|.
68
407D4000
push
00407D40
;
|Text
=
"Hello
World"
00407CCA
|.
6A
00
push
0
;
|hOwner
=
NULL
00407CCC
|.
E8
97C8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
00407CD1
|>
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
存儲通過xor
進(jìn)行了清零,然后用的cmp
做減法
然后判斷跳。
還有一種就是函數(shù)的返回值了。當(dāng)函數(shù)返回Boolean值或
指針
或
0
值時。
函數(shù)的返回值得也是不行的
00407CE0
|.
BB
64000000
mov
ebx,
64
00407CE5
|.
B8
5A000000
mov
eax,
5A
00407CEA
|.
E8
A1FFFFFF
call
00407C90
00407CEF
|.
3BD8
cmp
ebx,
eax
00407CF1
|.
7D
13
jge
short
00407D06
00407CF3
|.
6A
00
push
0
;
/Style
=
MB_OK|MB_APPLMODAL
00407CF5
|.
68
747D4000
push
00407D74
;
|Title
=
"Hello
World"
00407CFA
|.
68
747D4000
push
00407D74
;
|Text
=
"Hello
World"
00407CFF
|.
6A
00
push
0
;
|hOwner
=
NULL
00407D01
|.
E8
62C8FFFF
call
<jmp.&user32.MessageBoxA>
;
\MessageBoxA
00407D06
|>
8D55
FC
lea
edx,
dword
ptr
[ebp-4]
但是我們隨便Google一下test指令,
找到的破解的test的形式有如下幾種等:
1)TEST
EAX,EAX
2)TEST
EBX,EBX
3)TEST
ESI,ESI
4)TEST
EDI,EDI
這種直接邏輯與寄存器的比較多。
含存儲器的呢?
5)test
al,1
含一個立即數(shù)
6)test
ebp,esi
總之還有其他形式的test
,
但是以test
eax,eax最多,
因為Windows
API多對eax做了優(yōu)化,
當(dāng)使用
if
檢測是否返回0
時,
就要使用test指令,
更多有待總結(jié)。浮點數(shù)的幾種表示方法浮點二進(jìn)制表示浮點數(shù)是由三部分組成的:符號、尾數(shù)、指數(shù)。以數(shù)字-1.23456X10^5為例,其中“-”是符號,表示該浮點數(shù)是負(fù)數(shù),1.23456是尾數(shù),5是指數(shù)。IEEE二進(jìn)制浮點數(shù)的表示Intel微處理器使用IEEE發(fā)布的Standard754-1985forBinaryFloating-PointArithmetic中規(guī)定的三種浮點二進(jìn)制存儲格式。見下表。格式說明單精度32位:符號占1位、指數(shù)占8位、尾數(shù)中的小數(shù)部分占23位??杀硎镜拇笾路秶?^-126~2^127,也稱為短實數(shù)雙精度64位:符號占1位、指數(shù)占11位、尾數(shù)中的小數(shù)部分占52位??杀硎镜拇笾路秶?^-1022~2^1023,也稱為長實數(shù)擴展精度80位:符號占1位、指數(shù)占16位、尾數(shù)中的小數(shù)部分占63位??杀硎镜拇笾路秶?^-16382~2^16383,也稱為擴展實數(shù)三種格式非常相似,因此這里重點講述單精度格式。見下圖。圖中最高有效位(MSB)在左邊:1823符號指數(shù)尾數(shù)中的小數(shù)部分符號二進(jìn)制浮點數(shù)的符號由一個符號位便是,如果該位為1表示負(fù)數(shù),為0表示正數(shù)。浮點數(shù)的0是正數(shù)。尾數(shù)在形如mXb*e的表達(dá)式表示的浮點數(shù)中,m稱為尾數(shù),b是基數(shù),e是指數(shù)。尾數(shù)部分m是一個十進(jìn)制小數(shù)。大家知道的二進(jìn)制,十進(jìn)制和十六進(jìn)制的加權(quán)進(jìn)位表示法?,F(xiàn)在可以把同樣的概念擴展到數(shù)字的小數(shù)部分。例如十進(jìn)制數(shù)123.154可以表示為表達(dá)式的和:123.154=(1X10^2)+(2X10^1)+(3X10^-0)+(1X10^-1)+(5X10^-2)+(4X10^-3)二進(jìn)制浮點數(shù)的表示方法類似,只要用2為基數(shù)計算位權(quán)值即可。例如浮點數(shù)二進(jìn)制值11.1011可表示為:11.1011=(1X2^1)+(1X2^0)+(1X2^-1)+(0X2^-2)+(1X2^-3)+(1X2^-4)另一種表示小數(shù)點后面的值的方法是用以2的幕為分母的分?jǐn)?shù)之和表示,例如.1011=1/2+0/4+1/8+1/16=11/16得到分?jǐn)?shù)表示的方法是相當(dāng)直觀的。二進(jìn)制數(shù)1011實際上是十進(jìn)制數(shù)11,可用1011(十進(jìn)制數(shù)11)做分?jǐn)?shù)的分子。假設(shè)e是二進(jìn)制小數(shù)點后的有效數(shù)字的位數(shù),那么分母就是2^e。在該例子中e=4,因此分母2^e=16。下表中給出了另外一些二進(jìn)制浮點表示轉(zhuǎn)換成十進(jìn)制分?jǐn)?shù)的例子。表1中的最后一項是23位規(guī)格化尾數(shù)所以能存儲的最小分?jǐn)?shù)。表2中列出了另一些例子,例子中分別給出了二進(jìn)制浮點數(shù)以及與其等價的分?jǐn)?shù)和十進(jìn)制數(shù)。表1二進(jìn)制浮點數(shù)轉(zhuǎn)換成分?jǐn)?shù)二進(jìn)制浮點數(shù)十進(jìn)制分?jǐn)?shù)值11.1133/4101.001153/161101.1001011337/640.001015/321.01113/80.000000000000000000000011/8388608表2二進(jìn)制和十進(jìn)制分?jǐn)?shù)二進(jìn)制浮點數(shù)十進(jìn)制分?jǐn)?shù)值十進(jìn)制值.11/2.5.011/4.25.0011/8.125.00011/16.0625.000011/32.03125尾數(shù)的精度連續(xù)實數(shù)的整體不可能以有限個數(shù)據(jù)位的浮點格式表示。例如,假設(shè)使用一種簡化的格式表示浮點數(shù),其中尾數(shù)占5個數(shù)據(jù)位,那么就沒有辦法表示二進(jìn)制數(shù)1.1111和二進(jìn)制數(shù)10.0000之間的實數(shù)了。因此表示二進(jìn)制數(shù)1.11111就需要更高精度的尾數(shù)。類似的結(jié)論可以推廣到IEEE雙精度格式,53位的尾數(shù)不能表示需要54或更多個數(shù)據(jù)位的二進(jìn)制數(shù)字。指數(shù)單精度浮點數(shù)的指數(shù)是以8位無符號正數(shù)的格式存儲的,實際存儲的是指數(shù)值與127相加的和。以數(shù)字1.101X2^5為例,指數(shù)(5)與127相加的和(十進(jìn)制132,二進(jìn)制10100010)存儲在指數(shù)部分。下表給出了一些指數(shù)的例子。其中第一列是有符號十進(jìn)制整數(shù),第二列是調(diào)整后的值,最后一列是調(diào)整后的整數(shù)對應(yīng)的二進(jìn)制值。調(diào)整后的指數(shù)部分總是正數(shù)(在1~254之間),實際指數(shù)范圍是-126~+127。之所以選擇這個范圍,是為了避免最小可能的指數(shù)的倒數(shù)發(fā)生溢出(這里由于如果最小的指數(shù)選擇了-127,那么-127+127=0)指數(shù)(E)調(diào)整后(E+127)二進(jìn)制值+513210000100012701111111-1011701110101+12725411111110-126100000001-112601111110二進(jìn)制浮點數(shù)的正規(guī)化大多數(shù)浮點二進(jìn)制數(shù)都是以正規(guī)化的格式存儲,以便能夠使得尾數(shù)的精度最大化。對于任何給定的浮點二進(jìn)制數(shù),可通過移動小數(shù)點,使小數(shù)點前僅有一個數(shù)字“1”從而使其正規(guī)化,指數(shù)表示小數(shù)點向左(正數(shù))或向右移動(負(fù)數(shù))的位數(shù)??聪旅胬游凑?guī)化格式正規(guī)化格式1110.11.1101X2^3.0001011.01X2^-4101001.1.010001X2^6非正規(guī)化值:二進(jìn)制浮點正規(guī)化操作的逆過程稱為逆正規(guī)化,可通過移動二進(jìn)制小數(shù)點直到指數(shù)為零。如果指數(shù)部分使正數(shù)n,那么向右移動小數(shù)點n位;如果指數(shù)部分是負(fù)數(shù)n,那么向左移動小數(shù)點n位。如果需要,開頭的空位應(yīng)以0填充。IEEE表示法實數(shù)編碼一旦符號位、指數(shù)和尾數(shù)域進(jìn)行了正規(guī)化和編碼,得到一個完整的二進(jìn)制IEEE短實數(shù)就非常容易了。例如,二進(jìn)制值1.101X2^0可表示如下:符號位:0(因為是正數(shù))指數(shù):01111111(因為指數(shù)是00+127=127=01111111)小數(shù):10100000000000000000000(因為單精度短實數(shù)尾數(shù)中小數(shù)部分占23位)調(diào)整后的指數(shù)01111111是十進(jìn)制數(shù)127,所有正規(guī)化后的二進(jìn)制尾數(shù)在小數(shù)點前面都有一個1,因此對該位就無需顯式編碼了。下表中給出了幾個例子:單精度浮點數(shù)位編碼的例子二進(jìn)制調(diào)整后的指數(shù)值符號、指數(shù)和尾數(shù)-1.1112710111111111000000000000000000000+1101.10113001000001010110100000000000000000-.0010112410111110001000000000000000000000+100111.013201000010000111000000000000000000+000000110101112000111100010101100000000000000000IEEE規(guī)范中還規(guī)定了幾類實數(shù)和非實數(shù)的編碼:正數(shù)0和負(fù)數(shù)0反向正規(guī)化的有限數(shù)正規(guī)化的有限數(shù)正無窮和負(fù)無窮非數(shù)字值(NaN)不確定數(shù)Intel浮點單元使用不確定數(shù)響應(yīng)一些無效的浮點操作。正規(guī)化和反向正規(guī)化:正規(guī)化的有限數(shù)是0到無窮大之間的所有可以編碼為正規(guī)化實數(shù)的非0有限值。盡管乍看起來所有非零浮點數(shù)都可以正規(guī)化,不過事實上在值非常接近于0時這是不可能的。由于指數(shù)范圍的限制,F(xiàn)PU有可能不能把二進(jìn)制的小數(shù)點移動到正規(guī)化的位置。假設(shè)FPU的計算結(jié)果是1.0101111X2^-129,其指數(shù)太小無法在單精度實數(shù)中存儲,這時將產(chǎn)生一個下溢出異常,可通過向左移動小數(shù)點(每次一位)使其正規(guī)化,直到指數(shù)落在有效的范圍內(nèi)為止:例1.01011110000000000001111X2^-1290.10101111000000000000111X2^-1280.01010111100000000000011X2^-1270.00101011110000000000001X2^-126在這個例子中,由于移動了小數(shù)點,精度會有一些損失。正無窮和負(fù)無窮:正無窮(+∞)表示最大的正實數(shù),負(fù)無窮(-∞)表示最小的負(fù)實數(shù)??梢员容^無窮值和其他值:-∞小于+∞,-∞小于任何有限數(shù),+∞大于任何有限數(shù)。正無窮和負(fù)無窮都能用來表示溢出。非數(shù)字(NaN):NaN是不表示任何有效實數(shù)的位序列。IA-32體系結(jié)構(gòu)包含兩種類型的NaN:quietNaN可通過大多數(shù)算術(shù)運算而不會導(dǎo)致任何異常;signallingNaN可用于產(chǎn)生一個無效操作異常。編譯器可以用SignallingNaN值填充未初始化的數(shù)組,對該數(shù)組進(jìn)行任何計算的企圖都會引發(fā)一個異常。quietNaN可用于存放調(diào)試會話產(chǎn)生的診斷信息。浮點單元不會試圖對NaN執(zhí)行操作。IA-32手冊詳細(xì)描述了一套規(guī)則,用于確定以這兩種類型的NaN組合作為操作數(shù)時指令執(zhí)行的結(jié)果。特殊值的編碼:下表列出了浮點操作中經(jīng)常遇到的幾個特殊值的編碼。標(biāo)記位的位置既可以是0,也可以試1。QNaN表示quietNaN,SNaN表示signallingNaN。特殊的單精度浮點值的編碼值符號、指數(shù)、尾數(shù)正數(shù)000000000000000000000000000000000負(fù)數(shù)010000000000000000000000000000000正無窮01111111100000000000000000000000負(fù)無窮11111111100000000000000000000000QNaNx111111111xxxxxxxxxxxxxxxxxxxxxxxxxSNaNx111111111xxxxxxxxxxxxxxxxxxxxxxxxx*SNaN的尾數(shù)域以0開始,但是其余x表示的域中至少要有一個為1。把十進(jìn)制分?jǐn)?shù)轉(zhuǎn)換為二進(jìn)制實數(shù)如果十進(jìn)制分?jǐn)?shù)可以很容易地表示為1/2+1/4+1/8+......的格式,那么就很容易得到其對應(yīng)的二進(jìn)制實數(shù)。下表中的左邊一列中的大部分分?jǐn)?shù)一眼上去都不容易轉(zhuǎn)換成二進(jìn)制,不過如果寫成第二列的格式就容易多了。十進(jìn)制分?jǐn)?shù)和二進(jìn)制實數(shù)的例子十進(jìn)制分?jǐn)?shù)分解為二進(jìn)制實數(shù)1/21/2.11/41/4.013/41/2+1/4.111/81/8.0017/81/2+1/4+1/8.1113/81/4+1/8.0111/161/16.00013/161/8+1/16.00115/161/4+1/16.0101很多實數(shù),如1/10(0.1)或1/100(.01),不能用有限個二進(jìn)制數(shù)字位表示,這樣的分?jǐn)?shù)只能近似表示為若干以2的幕為分母的分?jǐn)?shù)之和。想想貨幣值如$39.95會受什么影響。另一種方法:使用二進(jìn)制長除法。把十進(jìn)制分?jǐn)?shù)轉(zhuǎn)換成二進(jìn)制數(shù)時如果涉及到的十進(jìn)制值比較小,可以使用一種很方便的方法:首先把分子和分母都轉(zhuǎn)換成二進(jìn)制值,然后再進(jìn)行除法操作。例如,十進(jìn)制值0.5可表示成分?jǐn)?shù)5/10,十進(jìn)制5是二進(jìn)制值0101,十進(jìn)制值10是二進(jìn)制值1010,執(zhí)行下面的除法,我們發(fā)現(xiàn)商是二進(jìn)制值0.1:_____.1__________1010|0101.0-1010___________0在被除數(shù)減去1010后余數(shù)為0時,除法終止。因此十進(jìn)制分?jǐn)?shù)5/10等于二進(jìn)制值0.1,我們稱上面這種方法為二進(jìn)制長除法。PS來自于DePaul大學(xué)的HarveyNice。例子:以二進(jìn)制數(shù)表示0.2。下面把十進(jìn)制的0.2(2/10)轉(zhuǎn)換成二進(jìn)制值,使用長除法。首先,把二進(jìn)制值10除以1010(十進(jìn)制值10):___.00110011(等等)_________________1010|10.000000001010__________11001010___________100001010____________11001010_____________等等第一個足夠大的余數(shù)是10000,在除以1010之后,余數(shù)是110,在末尾添加一個0,新的被除數(shù)是1100,除以1010后,余數(shù)是10,再添加3個0,新的被除數(shù)是10000,這等于進(jìn)行第一次除法操作時被除數(shù)的值。從這點開始,商中重復(fù)出現(xiàn)0011,因此我們得知準(zhǔn)確的商是無法得到的。0.2不能用有限個二進(jìn)制位表示。0.2的單精度編碼的尾數(shù)部分是00110011001100110011001把單精度值轉(zhuǎn)換成十進(jìn)制數(shù)下面是在把IEEE單精度值轉(zhuǎn)換成十進(jìn)制數(shù)時的推薦步驟:1。如果MSB(最高有效位)是1,該值為負(fù)數(shù),否則為正數(shù)。2。接下來的8位表示指數(shù),減去二進(jìn)制值01111111(十進(jìn)制值127),得到未調(diào)整的值數(shù)值,把未調(diào)整的指數(shù)值轉(zhuǎn)換成十進(jìn)制數(shù)。3。接下來的23位表示尾數(shù),注意尾數(shù)小數(shù)點前面有一個被省略的“1.”,尾數(shù)尾部的0可以忽略。這時就可以使用第一步中得到的符號位、第二步中得到的指數(shù)以及本步驟中得到的尾數(shù)創(chuàng)建一個浮點二進(jìn)制數(shù)了。4。對第三步得到的浮點數(shù)進(jìn)行逆規(guī)格化操作(根據(jù)指數(shù)相應(yīng)地移動小數(shù)點,指數(shù)為正則右移動,指數(shù)為負(fù)則左移動)。5。從左到右,使用位權(quán)表示方法得到浮點數(shù)的2的次幕之和的表示,進(jìn)而得到相應(yīng)的十進(jìn)制數(shù)。例子:把IEEE浮點數(shù)(01000001001011000000000000000000)轉(zhuǎn)換成十進(jìn)制數(shù)1.該數(shù)是正數(shù)。2.未調(diào)整的指數(shù)值是00000011,也就是十進(jìn)制數(shù)3。3.組合符號位、指數(shù)和尾數(shù)得到二進(jìn)制數(shù)+1.01011X2^34.逆正規(guī)化后的二進(jìn)制數(shù)是+1010.115.對應(yīng)的十進(jìn)制值是+103/4或+10.75提到編碼,只要學(xué)過一點匯編的人都應(yīng)該知道一些常用的匯編指令的編碼,比如:B878563412,一看到B8就知道對應(yīng)的匯編指令是MOVEAX,0X12345678占用5字節(jié),一看到E8就知道是E8后面跟的是JMP的4字節(jié)偏移,一見90就知道是NOP,因為這些指令都很常用,編碼也都很簡單,想必大家對這些指令編碼都熟記于心了。如果提到MOVEBX,XXXXXXXXMOVECX,XXXXXXX這些指令也許大家對指令編碼就不怎么記得了,因為X86的編碼太多了,要把他全記住那可不是件容易的事。其實要把X86的編碼指令記住并不是件難事,因為X86編碼指令看似復(fù)雜龐大,其實這大部分編碼有是有規(guī)律可尋的。在這里先說組寄存器:01234567EAXECXEDXEBXESPEBPESIEDI01234567ALCLDLBLAHCHDHBH不知道各位同學(xué)當(dāng)年學(xué)匯編的時候寄存器是不是按這個順序記的,如果是按這個順序記住的話,接下來講的編碼你可能一看就記住了B8是MOVEAX大家都很清楚的記得,那么B9呢?B9就是MOVECX,BAMOVEDX聰明的同學(xué)應(yīng)該很快的看出規(guī)律出來了吧!BB是MOVEBX,BC是MOVESP
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 商業(yè)合作備忘錄與協(xié)議條款
- 貴州國企招聘2025貴州省水利水電工程咨詢有限責(zé)任公司招聘12人筆試參考題庫附帶答案詳解
- 2025遼寧沈陽地鐵集團(tuán)有限公司所屬公司招聘11人筆試參考題庫附帶答案詳解
- 2025河南三門峽盧氏縣國有資本投資運營有限公司招聘6人筆試參考題庫附帶答案詳解
- 2025四川南充臨江東方建設(shè)集團(tuán)有限公司招聘11人筆試參考題庫附帶答案詳解
- 2025中國華冶科工集團(tuán)有限公司校園招聘280人筆試參考題庫附帶答案詳解
- 終止合作合同協(xié)議書
- 姐第合同協(xié)議書
- 交房合同協(xié)議書
- 洗滌合同協(xié)議書
- 防汛抗洪培訓(xùn)課件
- 公司管理制度編號方法
- 大數(shù)據(jù)發(fā)展在實現(xiàn)高中數(shù)學(xué)精準(zhǔn)教學(xué)中應(yīng)用分析
- 深度學(xué)習(xí)賦能:單幅圖像超分辨率重建算法的探索與突破
- 世界贈予我的混聲三部合唱線譜徐
- 【特易資訊】2025中國二手車行業(yè)出口分析及各國進(jìn)口政策影響白皮書
- 2025風(fēng)電機組螺栓在線監(jiān)測技術(shù)規(guī)范
- 2023年同等學(xué)力申碩《英語》試題真題及答案
- 學(xué)校教學(xué)管理指導(dǎo)手冊
- 風(fēng)電項目施工工藝及流程
- 《現(xiàn)代農(nóng)業(yè)生物技術(shù)育種方法》課件
評論
0/150
提交評論