匯編指令學(xué)習(xí)總結(jié)_第1頁
匯編指令學(xué)習(xí)總結(jié)_第2頁
匯編指令學(xué)習(xí)總結(jié)_第3頁
匯編指令學(xué)習(xí)總結(jié)_第4頁
匯編指令學(xué)習(xí)總結(jié)_第5頁
已閱讀5頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論