第4章 主要なニーモニックの説明 その 1

前へ  戻る     次へ

これから書かれていることはOllyの実践的な使い方ではなく、
アセンブラニーモニックの説明を初めとする基本的な使い方です。

それでは今回では残りの主要なニーモニックの説明に入ります。(その1)

ニーモニックのインデックスからサンプルプログラムがダウンロードできます。


○PUSHとPOP

書式:PUSH src

POP dest


 一時的にデータを保持するための領域にスタックというものがあります。PUSHはスタックポインタ(ESP)をdecrementし、srcをスタックのトップに転送します。POPは逆で、destにスタックのトップのデータを転送し、スタックポインタをincrementします。srcdestはレジスタかメモリ参照が入ります。

あれこれ言うよりサンプル見たほうが理解は早いかと思いますw

 

00401000 >/$ B8 78563412    MOV EAX,12345678

00401005  |. BA 32547698    MOV EDX,98765432

0040100A  |. 50             PUSH EAX                          ;  EAXをスタックにプッシュ

0040100B  |. 52             PUSH EDX                          ;  EDXをスタックにプッシュ

0040100C  |. 58             POP EAX                           ;  EAXにスタックをポップ

0040100D  |. 5A             POP EDX                           ;  EDXにスタックをポップ

0040100E  |. FF35 00304000  PUSH DWORD PTR DS:[403000]        ;  メモリ403000をスタックにプッシュ

00401014  |. FF35 04304000  PUSH DWORD PTR DS:[403004]        ;  メモリ403004をスタックにプッシュ

0040101A  |. 8F05 00304000  POP DWORD PTR DS:[403000]         ;  メモリ403000にスタックをポップ

00401020  |. 8F05 04304000  POP DWORD PTR DS:[403004]         ;  メモリ403004にスタックをポップ

00401026  |. 6A 00          PUSH 0                            ; /ExitCode = 0

00401028  \. E8 01000000    CALL <JMP.&kernel32.ExitProcess>  ; \ExitProcess

 

0040100A0040100DEAXEDXの交換、0040100E00401020[403000] [403004]の交換をしています。ちなみに、単に交換するだけならXCHG dest,srcでできますがw

スタックももちろんメモリにあります。ダンプウィンドウでESPの値のアドレスに飛んでみればスタックウィンドと同じものが見えます。実行ファイルもメモリ上にロードされて実行されているので00401000とかに飛んでみれば、B8 78 56 34 12・・・という数値が見えます。


○NOTとANDとORとXOR
書式:NOT src

AND dest,src

OR dest,src

XOR dest,src

NOT srcsrcのビットを反転させます。

ANDORXORもビットレベルの処理で、以下のようになります。

AND論理積

OR論理和

XOR排他的論理和

0 AND 0 = 0

0 AND 0 = 0

0 AND 0 = 0

0 AND 1 = 0

0 AND 1 = 1

0 AND 1 = 1

1 AND 0 = 0

1 AND 0 = 1

1 AND 0 = 1

1 AND 1 = 1

1 AND 1 = 1

1 AND 1 = 0

両ビットが1の時のみ1

両ビットが0の時のみ0

両ビットが一致する時のみ0

上記の処理を対応するビットに対して行い、結果をdestに転送します。例えば、1010 AND 1101 = 1000で、1010 OR 1101 = 1111です。排他的論理和はその特徴として、「dest = srcなら必ず0になる」,「排他的論理和を取った値(論理演算結果)をdest(あるいはsrc)で排他的論理和を取るとsrc(あるいはdest)になる」というものがあります。後者はこの性質を利用して暗号化なんかに利用されているらしいです。

 

00401000 >/$ B8 02000000    MOV EAX,2                         ;  EAX0010bを転送(-3になる)

00401005  |. F7D0           NOT EAX                           ;  1010bのビットを反転

00401007  |. B8 0E000000    MOV EAX,0E                        ;  EAX1110bを転送

0040100C  |. BA 05000000    MOV EDX,5                         ;  EDX0101bを転送

00401011  |. 23C2           AND EAX,EDX                       ;  1110b0101bで論理積を取る

00401013  |. 0BC2           OR EAX,EDX                        ;  0100b0101bで論理和を取る

00401015  |. BA 0F000000    MOV EDX,0F                        ;  EDX1111bを転送

0040101A  |. 33C2           XOR EAX,EDX                       ;  0101b1111bで排他的論理和を取る

0040101C  |. 33C2           XOR EAX,EDX                       ;  1010b1111bで排他的論理和を取る

0040101E  |. 33C0           XOR EAX,EAX                       ;  EAX0をセット

00401020  |. 6A 00          PUSH 0                            ; /ExitCode = 0

00401022  \. E8 01000000    CALL <JMP.&kernel32.ExitProcess>  ; \ExitProcess

 

0040101CEAX0101b5)に戻っています。0040101Eでは同じ値で排他的論理和を取っているので0になります。MOV EAX,0だと5BYTEも必要になるのに対して、これだと2BYTEEAXを初期化できますね。


○CMPとTEST
書式:CMP  src1,src2

TEST src1,src2

いっしょに並べたら怒られそうな気もしますが・・・、どちらも条件分岐などに利用されることが多いのでw

CMP  src1,src2src1src2を比較し、結果にしたがってフラグをセットします。やってることは計算結果を破棄するSUB命令です(SUBでもフラグのセットは行われている)。これで、src1,src2の比較の結果(どちらが大きいか、同じかなど)がフラグレジスタに一時的に保存されます。

TEST src1,src2は結果を破棄するAND命令です。src1src2で論理積を取り、0になれば0フラグをセットします。

セットしたフラグに応じて条件付きの処理が行えます。

フラグはレジスタウィンドウのCPAZSTDOと縦に書かれた所(フラグレジスタ)で確認できます。

 

<よく使うフラグ>

C(キャリーフラグ)

算術演算で繰り上がり(加算)や桁借り(減算)した時に「1」、しなかった場合は「0」になる。

Z(ゼロフラグ)

演算結果が0になった場合に「1」、それ以外なら「0」になる。

一番重要!

S(サインフラグ)

演算結果がマイナスになった場合に「1」になる。このフラグは演算結果の最上位ビットがそのまま反映されている。

 

00401000 >/$ B8 02000000    MOV EAX,2

00401005  |. BA 03000000    MOV EDX,3

0040100A  |. 3BC2           CMP EAX,EDX                       ;  23を比較→CS1Z0

0040100C  |. BA 01000000    MOV EDX,1

00401011  |. 3BC2           CMP EAX,EDX                       ;  21を比較→CZS0

00401013  |. BA 02000000    MOV EDX,2

00401018  |. 3BC2           CMP EAX,EDX                       ;  22を比較→CS0Z1

0040101A  |. B8 0F000000    MOV EAX,0F

0040101F  |. BA 05000000    MOV EDX,5

00401024  |. 85C2           TEST EDX,EAX                      ;  0101b1111bで論理積→Z0

00401026  |. B8 0A000000    MOV EAX,0A                        ;  EAX1010bを転送

0040102B  |. 85C2           TEST EDX,EAX                      ;  0101b1010bで論理積→Z1

0040102D  |. 6A 00          PUSH 0                            ; /ExitCode = 0

0040102F  \. E8 00000000    CALL <JMP.&kernel32.ExitProcess>  ; \ExitProcess

 

Z以外は「あ〜なんか大小比較してるぞぉ〜」って程度の認知でもいいですw

ちなみに、フラグレジスタをダブルクリックでフラグのONOFFが切り替えられます。


○JX
書式:JX dest

条件分岐命令です。JXなんてニーモニックはありません。Xにはフラグを指定する文字が入ります。色々ありますが、雰囲気から察してやって下さいw destにはアドレスが入り、条件を満たしている時はそのアドレスにジャンプします。

主要なものを下に挙げます。

 

命令

意味

JE

Jmup if equal

Zフラグが立っていればジャンプ

JZ

Jmup if zero

Zフラグが立っていればジャンプ

JNE

Jmup if not equal

Zフラグが立っていなければジャンプ

JNZ

Jmup if not zero

Zフラグが立っていなければジャンプ

JA

Jmup if avobe

比較の結果、上なら(符号なし)ジャンプ

JG

Jmup if great

比較の結果、大きいなら(符号付き)ジャンプ

JNA

Jmup if not avobe

比較の結果、上でなければ(符号なし)ジャンプ

JNG

Jmup if not great

比較の結果、大きくなければ(符号付き)ジャンプ

JB

Jmup if below

比較の結果、下なら(符号なし)ジャンプ

JL

Jmup if less

比較の結果、小さいなら(符号付き)ジャンプ

JNB

Jmup if not below

比較の結果、下でなければ(符号なし)ジャンプ

JNL

Jmup if not less

比較の結果、小さくなければ(符号付き)ジャンプ

 

 JAEJmup if avobe or equal)のように末尾にEを加えれば等号付きの条件(要するにJAEJNB)になります。

 また、JMP dest無条件分岐になります。(もちろん重要

 

00401000 >/$ B8 01000000    MOV EAX,1

00401005  |. BA FFFFFFFF    MOV EDX,-1

0040100A  |. 3BD0           CMP EDX,EAX                        ;  -11を比較

0040100C  |. 7C 05          JL SHORT jx.00401013               ;  -11なのでジャンプ

0040100E  |. BA 00000000    MOV EDX,0                          ;  実行されない

00401013  |> 3BD0           CMP EDX,EAX                        ;  FFFFFFFF1を比較

00401015  |. 72 05          JB SHORT jx.0040101C               ;  FFFFFFFF1で無いのでジャンプしない

00401017  |. B9 04000000    MOV ECX,4                          ;  ループカウンタをセット

0040101C  |> 49             /DEC ECX                           ; ループカウンタをデクリメント

0040101D  |.^75 FD          \JNZ SHORT jx.0040101C        ;  4回ループ

0040101F  |. 6A 00          PUSH 0                             ; /ExitCode = 0

00401021  \. E8 00000000    CALL <JMP.&kernel32.ExitProcess>   ; \ExitProcess

 

 DECなど演算処理は普通フラグの変化を伴います。上記の例ではECXをデクリメントし続けて、0になったら分岐しなくなると言うことですね。


サンプルプログラムの著作権とかは面倒なので放棄してます。好きに使ってもらって構いません。


 

前へ  戻る     次へ