最終更新:2015-07-20 (月) 05:53:59 (3195d)  

よく使うASM命令ベスト100位に説明つけてみた
Top / よく使うASM命令ベスト100位に説明つけてみた

最低限これだけ覚えておけばきっと解析できる命令

関数呼び出しやEIP変更関連の命令

  • PUSH55?とか。対象のレジスタによるスタックへ値を格納
    POPスタックから値を取り出す
    CALLスタックに次の実行命令のアドレスを入れてジャンプ
    LEAVE?RETの前に置かれるもの("MOV ESP, EBP"+"POP EBP"と同じ)
    RET?スタックのトップにある値を取り出してそこへジャンプ
    JMPE9?/EA?/EB指定アドレスへジャンプ

値の操作系の命令

  • MOVBxレジスタ値やメモリの値を転送
    MOVZX?渡したレジスタ値やメモリ値のサイズが異っても転送可能なMOV
    LEA説明しにくい。まぁ[]の中の計算結果がレジスタへ入ると覚えておけばおK
    XCHG?2つのオペランドを交換する(XCHG EAX, EBXでEAXとEBXの値が交換される)
    ADD値を加算(足し算)
    SUB値を減算(引き算)
    INC?インクリメント 値に1加算
    DEC?デクリメント 値から1減算

条件分岐系の命令(重要)

  • CMP値を評価してフラグに反映
    TESTフラグだけ変化するAND命令(真 OR 偽 だけを判断する時によく使う)
    JE?ZF=1 同じならジャンプ
    JZ?JEと同じ意味
    JNE?ZF=0 違うならジャンプ
    JNZJNEと同じ意味
    JA?CF=0 && ZF=0 符号なしで、大きいならジャンプ
    JAE?CF=0 符号なしで、以上ならジャンプ
    JBCF=1 符号なしで、小さいならジャンプ
    JBE?CF=1 && ZF=1 符号なしで、以下ならジャンプ
    JL?SF!=OF 符号ありで、小さいならジャンプ
    JLE?ZF=1 OR SF!=OF 符号あり以下ならジャンプ
    JG?ZF=0 && SF=OF 符号ありで、大きいならジャンプ
    JGE?SF=OF 符号ありで、以上ならジャンプ

ビット操作系の命令

  • XOR?ただのXOR(C言語の ^ ←これ)
    ANDただのAND(C言語の & ←これ)
    ORただのOR (C言語の | ←これ)
    SHL?左方向にシフト(C言語でいう << ←これ)
    SHR右方向にシフト(C言語の >> ←これ)
    NOT1の補数値にする(要するにビット反転命令)
    NEG?2の補数値にする(符号ありの値に対して、符号を反転させる)

データ列の操作命令(文字列処理など)

  • REP?ECXが0になるまで次の命令を繰り返す(比較命令時はZFフラグも見る)
    MOVS?REPと組み合わせることで大量のデータを一気に転送できる(EDIやESIと連動)

デバッグ系命令

  • INT3?デバッグ用割り込み
    NOP何もしない

ベスト100

  • MOVレジスタ値やメモリの値を転送
    PUSHスタックへ値を格納
    ADD値を加算(足し算)
    CALLスタックに次の実行命令のアドレスを入れてジャンプ
    INT3?デバッグ用割り込み
    POPスタックから値を取り出す
    CMP値を評価してフラグに反映
    JE?ZF=1 同じならジャンプ
    LEA説明しにくい。まぁ[]の中の計算結果がレジスタへ入ると覚えておけばおK
    NOP何もしない
    TESTフラグだけ変化するAND命令(真 OR 偽 だけを判断する時によく使う)
    JMP指定アドレスへジャンプ
    JNE?ZF=0 違うならジャンプ
    XOR?ただのXOR(C言語の ^ ←これ)
    INC?インクリメント 値に1加算
    RET?スタックのトップにある値を取り出してそこへジャンプ
    ANDただのAND(C言語の & ←これ)
    DEC?デクリメント 値から1減算
    SUB値を減算(引き算)
    ORただのOR(C言語の | ←これ)
    OUTS?外部デバイスの入出力ポートへデータを送る(REPと組み合わせて使おう)
    JBCF=1 符号なしで、小さいならジャンプ
    (BAD?)できなかった命令?
    IMUL?符号ありの乗算(掛け算)EAXと渡された値を掛けてEDX:EAXへ入れる
    INS?外部デバイスの入出力ポートからデータを受け取る(REPと組み合わせて使おう)
    JL?SF!=OF 符号あり(マイナスの数値あり)で、小さいならジャンプ
    JAE?CF=0 符号なし(0が最小値)で、以上ならジャンプ
    LEAVE?RETの前に置かれるもの("MOV ESP, EBP"+"POP EBP"と同じ)
    POPA?全レジスタ分のデータをスタックから取り出し
    GS?
    MOVZX?渡したレジスタ値やメモリ値のサイズが異っても転送可能なMOV
    SBB?基本的にSUBと同じ(異なるのはCF=1の場合にさらに1を減算する点)
    ADC基本的にADDと同じ(異なるのはCF=1の場合にさらに1を加算する点)
    JBE?CF=1 && ZF=1 符号なしで、以下ならジャンプ
    MOVS?REPと組み合わせることで大量のデータを一気に転送できる(EDIやESIと連動)
    JGE?SF=OF 符号ありで、以上ならジャンプ
    ARPL?特権レベルを調整する(1行では説明不能、解析屋には必要ない?)
    SHR右方向にシフト(C言語の >> ←これ)
    FLD?ST0レジスタにデータを格納(浮動小数点系の演算でよく使われる)
    JA?CF=0 && ZF=0 符号なしで、大きいならジャンプ
    JO?OF=1 オーバーフローしたらジャンプ
    JLE?ZF=1 OR SF!=OF (符号あり)以下ならジャンプ
    SHL?左方向にシフト(C言語でいう << ←これ)
    FSTP?ST0レジスタからデータを取得(浮動小数点系の演算でよく使われる)
    REP?Xが0になるまで次の命令を繰り返す(比較命令時はZFフラグも見る)
    XCHG?2つのオペランドを交換する(XCHG EAX, EBXでEAXとEBXの値が交換される)
    ADDR16?
    FS?
    NEG?2の補数値にする(符号ありの値に対して、符号を反転させる)
    JSSF=1 マイナスならジャンプ
    STOS?EAXの値をES:EDIの指すメモリへ格納する(REPと組み合わせることで初期化処理になる)
    JNS?SF=0 マイナスじゃないならジャンプ
    MOVQ?MMXレジスタで使われるMOVで64ビット転送に使用する(最適化とかそういう話)
    FMUL?浮動小数点演算での掛け算(ST0と渡されたオペランドが掛けられる)
    JG?ZF=0 && SF=OF 符号ありで、大きいならジャンプ
    MOVAPS?XMMレジスタで使われるMOVで128ビット転送に使用する(これも最適化とかそういう話)
    SAR?符号ありで右シフト(シフト系は符号のありなしで少し複雑)
    BOUND?INT3と似たようなものだが、こちらは境界チェックの例外
    DATA16?
    IN外部デバイスの入出力ポートからデータを受け取る(INSのパワーダウン版?)
    REPZ?REPと同じだが、次の命令が転送命令ならREPを比較命令ならREPZを使うのが一般的らしい
    OUT外部デバイスの入出力ポートへデータを送る(OUTSのパワーダウン版?)
    CDQ?EAXレジスタを符号付き整数としてEDX:EAXに型変換する
    MOVSX?基本的に16ビット版MOV(メモリ上の16ビット以下のデータを転送する)
    PUSHA?全レジスタの値をスタックへ格納する
    FADD?浮動小数点演算での足し算(ST0と渡されたオペランドが足される)
    ROL?左方向へのローテート(CFは含まれない)
    AAS?アンパックBCDの減算結果ALを補正(繰り下がりが発生するとAH--)
    JNO?OF=0 オーバーフローでないならジャンプ
    ROR?右方向へのローテート(CFは含まれない)
    DSセグメントオーバーライドプリフィックス(データセグメント)
    JP?PF=1 PFが1ならジャンプ(JPEとも書く)
    FNSTSW?FSTフラグをオペランドへ転送(FSTSWとも書く)
    NOT1の補数、要するにビット反転命令
    CSセグメントオーバーライドプリフィックス(コードセグメント)
    FILD?符号付き整数を浮動小数点数に変換しST0へ格納
    LOCK?割り込み禁止に設定
    SETE?ZFフラグの値をオペランドへ格納
    SETNE?ZFフラグと逆の値をオペランドへ格納
    LODS?メモリの内容をEAXに読み込みESIをその分加算OR減算

参考