Log

アセンブリ言語 メモ2

1, x86におけるアセンブリ命令と記法

 

アセンブリ言語アセンブリ命令と呼ばれる命令の集合で記述されている。

アセンブリ命令はオペコードとオペランドの2つからできている。

オペコードは命令が操作の種類をしてする部分であり、オペランドはオペコードに夜操作の対象となる部分である。

 

x86 or x86-64には2つの記法が存在する。一つはintel記法、二つ目はat&t記法。

IDE or llydbgではデフォルトでintel記法で表現される。

 

example) movv命令でeaxレジスタに5を格納する

 

intel) mov eax, 5

at&t) mov $5, %eax

 

at&tはプレフィックスも異なる。また第二オペランドと第一オペランドintel記法と比べて逆である。

 

x86アセンブリではオペランドにメモリアドレスを指定して、そのアドレスに格納されている内容を参照することができる。

 

ebx registerに格納されたアドレスを参照し、そのアドレスに格納されている値をeaxレジスタに格納する

ebx 0x01001234 = 5

eax レジスタにも5が格納される。

mv eax, [ebx]

 

さらにメモリアドレスを参照する際に、そのメモリアドレスから変異(ディスプレースメント)を指定することもできる。

つまり、ebxレジスタに格納されているアドレスから+4の位置にあるアドレスのように、あるレジストリに格納されたアドレスを基準にして、一定分変化した位置を以下のように示すことができる

 

mov eax, [ebx+4]

 

変位に加えて、オフセットレジスタやスケーラを指定することができる。この場合ベースレジスタ+変位+オフセットレジスタ*スケーラの位置アドレスにアクセスすることになります

 

アセンブリ言語を扱うオペランドに対しても、サイズを明示しなくてないけない。

例えば32bit整数に対してmov命令を実行する場合、対応するサフィックスであるlをつけてmovlという命令を用いる。

 

サフィックス一覧

b:byte(8bit)

s;short(16bit)

w:word(16bit)

l:long(32bit)

q:qwad(64bit)

t:10byte(80bit 浮動小数)

 

 

基本的なアセンブリ命令

[データ転送命令]

mov命令はsrcオペランドの値をdestオペランドに移動します。しかし、移動した後もsrcオペランドの値が失われるわけではないので、コピーといった方がしっくりくるかもしません。

 

mov dest, src

 

lea命令はsrcオペランドのアドレスを計算して、そのアドレスをdestオペランドにロードする。アドレス計算に用いられる。青dレス計算とは

lea eax, [esp+0x40] のように変位などを含めたアドレス計算をすること。この場合、スタックポインタに指すアドレスから変位0x40を加えたアドレスがeaxに格納される。

 

lea dest, src

 

xchg命令はarg1オペランドとarg2オペランドの値を交換します

 

xchag dest1 , dest2

 

lodsbは[DS:ESI]のメモリの内容をBYTEすなわち1倍分ALレジスタに読み込む。読み込んだ後はESIレジスタを、DFレジスタに基づいて、読み込んだ分、加算または減算する。

 

push命令は、argオペランドの値をスタックにpushします。具体的にはESPレジスタの値をレジスタ幅分(32bitでは4byte, 64bitでは8byte)減算し、argオペランドをESPレジスタの示すスタックのトップに格納する。

pop命令はスタックからargオペランドへpopします。具体的にはESPレジスタの示すスタックのトップ値をargオペランドへ格納espレジスタの値をレジスタ幅分加算します。し、

 

pop dest

 

add命令はdestオペランドにsrcオペランドを加算した結果をdestオペランドに格納します。sub命令も同様に、destオペランドからsrcオペランドを減算した結果をでsトペランドに格納する。

 

add dest, src

sub dest, src

 

mul命令、srcオペランドにEAXレジスタの値を乗算し、結果の上位4byteをedxレジスタ、下位4byteをeaxレジスタに格納します。

 

cmp命令はsub命令と同じ減算をします。しかし、結果はオペランドに格納されずに破棄される。