第5章 主要なニーモニックの説明 その 2

前へ  戻る     次へ

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


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

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


○CALLとRETN

書式:CALL dest

RETN


 多くの場合、CALLdestに飛んで、RETNで戻ってきます。

CALLはその次のアドレス(プロシージャ・リンク情報)をスタックに転送し、destにジャンプします。

RETNはスタックのアドレスにジャンプします。

 

00401000 >/$ E8 07000000    CALL call.0040100C                    ;  40100Cをコール

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

00401007  \. E8 20000000    CALL <JMP.&kernel32.ExitProcess>      ; \ExitProcess

 

0040100C  /$ 55             PUSH EBP                              ;  EBPを退避

0040100D  |. 8BEC           MOV EBP,ESP                           ;  EBPESPを転送(ESPの退避)

0040100F  |. 56             PUSH ESI                              ;  ESIを退避

00401010  |. 57             PUSH EDI                              ;  EDIを退避

00401011  |. A1 00304000    MOV EAX,DWORD PTR DS:[403000]         ;  EAX[403000]=401020を転送

00401016  |. E8 0E000000    CALL call.00401029                    ;  401029をコール

0040101B  |. B8 01000000    MOV EAX,1                             ;  実行されない

00401020  |. 83C4 04        ADD ESP,4                             ;  スタックポインタを4足してポインタの補正

00401023  |. 5F             POP EDI                               ;  退避したEDIを戻す

00401024  |. 5E             POP ESI                               ;  退避したESIを戻す

00401025  |. 8BE5           MOV ESP,EBP                           ;  退避したESPを戻す

00401027  |. 5D             POP EBP                               ;  退避したEBPを戻す

00401028  \. C3             RETN                                  ;  401005にリターン

 

00401029  /$ 50             PUSH EAX                              ;  401020をプッシュ

0040102A  \. C3             RETN                                  ;  401020にリターン(40101Bではない)

 

ここでちょっと説明です。F8はステップ実行なので、CALLF8を使うとその中のプロシージャをまとめてすっ飛ばしますw CALLの中をトレースしたい時はF7(詳細ステップ実行)を使用しましょう〜。つまり今回は、F7だけ,もしくは401000401016F7を押せばその中も辿る事ができるって事です。

サンプルではCALLの次のアドレスに戻らない例を示していますが、まぁ稀なのであまり気にしなくてもいいですw

 

プロシージャプログラム内で繰り返し出現する処理を行なうために、一連の命令を一つの手順としてまとめたもの。例えば、シリアルのチェックルーチン(入力したシリアルが正しいか誤りかを調べるプロシージャ)は起動時,入力時,制限項目の実行時など色々なケースで利用されます。このチェックをそれぞれのケースにおいてCALLで呼び出せば、その処理の記述は一回で済みます。

 


○SETX
書式:SETX dest

Xの条件に従いdestにビットをセットします。Xの条件はJXと同じなので割愛・・・

よく見かけるのはSETEZEROフラグが立っていたら)とSETNEZEROフラグが立っていなかったら)です。destはバイトレジスタか、メモリ参照が入ります。

 

00401000 >/$ E8 15000000    CALL setx.0040101A

00401005  |. 83F8 00        CMP EAX,0                                ;  EAX0を比較

00401008  |. 0F94C2         SETE DL                                  ;  DLにビットをセットする

0040100B  |. E8 10000000    CALL setx.00401020

00401010  |. 0F95C2         SETNE DL                                 ;  DLにビットをセットしない

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

00401015  \. E8 12000000    CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess

0040101A  /$ A1 00304000    MOV EAX,DWORD PTR DS:[403000]

0040101F  \. C3             RETN

00401020  /$ A1 04304000    MOV EAX,DWORD PTR DS:[403004]

00401025  |. A9 00000000    TEST EAX,0                               ;  EAX0を論理比較

0040102A  \. C3             RETN

 

まぁこれは簡単でしょう〜w


○SHXとROX
書式:SHX dest,cnt

SAX dest,cnt

ROX dest,cnt

destcntの回数だけビットシフトするニーモニックです。

XにはRもしくはLが入り、それぞれ右ビットシフト,左ビッドシフトを意味します。

またCフラグのセットも行います。

それぞれの例として、101010101ビットシフトさせると以下のようになります。(8ビットの場合)

 

L

Cフラグ

 

R

Cフラグ

SHX

01010100

1

 

01010101

0

SAX

01010101

1

 

11010101

0

ROX

01010101

1

 

01010101

0

 

 

 

 

 

 つまり、最終的に押し出されたビットがCフラグにセットされ、1が押し出される場合、ROXでは最下段と最上段がつながっているようなシフトをします。SAXでは左ビットシフトではSHXと同じ挙動を示しますが、右ビットシフトの場合は最上位ビット(補数)を保持します。

 

LEA

書式:LEA dest,src

srcにはメモリ参照が入り、destに参照しているメモリのアドレスを転送します。

要するに、lea dest,[addr]とすると、destaddrを転送するってことです。いちいちサンプル作るほどの物でもないのでついでにw

 

00401000 >/$ B9 02000000      MOV ECX,2                            ;  ECX2をセット(ループカウンタみたいな物)

00401005  |> 83F9 02          /CMP ECX,2                           ;  ECX値がエラーかどうかのチェック

00401008  |. 7F 0D            |JG SHORT shx.00401017               ;  エラーだったらジャンプして終了

0040100A  |. 8D048D 00304000  |LEA EAX,DWORD PTR DS:[ECX*4+403000] ;  403000から12BYTE(3つ)のアドレステーブルを参照し、そのアドレスをEAXに転送

00401011  |. 8B00             |MOV EAX,DWORD PTR DS:[EAX]          ;  EAXの指定するアドレスの値(コール先)をEAXに転送

00401013  |. FFD0             |CALL EAX                            ;  EAXをコール

00401015  |.^EB EE            \JMP SHORT shx.00401005              ;  ループ

00401017  |> 6A 00            PUSH 0                               ; /ExitCode = 0

00401019  \. E8 52000000      CALL <JMP.&kernel32.ExitProcess>     ; \ExitProcess

0040101E   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

00401023   . D0E8             SHR AL,1                             ;  ALを右に1ビット論理シフト

00401025   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

0040102A   . D0E0             SHL AL,1                             ;  ALを左に1ビット論理シフト

0040102C   . B8 32547698      MOV EAX,98765432                     ;  EAX98765432を転送

00401031   . C1E8 08          SHR EAX,8                            ;  EAXを右に1バイト論理シフト

00401034   . C1E8 10          SHR EAX,10                           ;  EAXを右に2バイト論理シフト

00401037   . 49               DEC ECX                              ;  ECXをデクリメント

00401038   . C3               RETN

00401039   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

0040103E   . D0F8             SAR AL,1                             ;  ALを右に1ビット算術シフト

00401040   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

00401045   . D0E0             SHL AL,1                             ;  ALを左に1ビット算術シフト

00401047   . B8 32547698      MOV EAX,98765432                     ;  EAX98765432を転送

0040104C   . C1F8 08          SAR EAX,8                            ;  EAXを右に1バイト算術シフト

0040104F   . C1F8 10          SAR EAX,10                           ;  EAXを右に1バイト算術シフト

00401052   . 49               DEC ECX                              ;  ECXをデクリメント

00401053   . C3               RETN

00401054   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

00401059   . D0C8             ROR AL,1                             ;  ALを右に1ビットだけロケーショナルにシフト

0040105B   . B8 AA000000      MOV EAX,0AA                          ;  EAX10101010bを転送

00401060   . D0C0             ROL AL,1                             ;  ALを左に1ビットだけロケーショナルにシフト

00401062   . B8 32548709      MOV EAX,9875432                      ;  EAX98765432を転送

00401067   . C1C0 10          ROL EAX,10                           ;  EAXを左に2バイトだけロケーショナルにシフト

0040106A   . 68 17104000      PUSH shx.00401017                    ;  401017をスタックに転送して

0040106F   . C3               RETN                                 ;  401017にリターン

 

 0040102Cのように2バイトのシフトを行うと、上位16ビットが下位16ビットに来るため、レジスタで指定(AXなど)することができるようになります。

 ちょこっとだけプログラムを複雑にしてありますので、よくトレースして理解できるようにして下さいw

 ちなみに、0040100A00401013CALL [ECX*4+403000]と書いた方が一行で済んで短いんですが、LEAのためにかなり強引に盛り込んであるだけですw

 サンプル最長記録達成・・・


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


 

前へ  戻る     次へ