第3章 主要なニーモニックの説明 その 0
前へ 戻る
これから書かれていることはOllyの実践的な使い方ではなく、
アセンブラニーモニックの説明を初めとする基本的な使い方です。
それでは今回では本格的に主要なニーモニックの説明に入ります。
ニーモニックのインデックスからサンプルプログラムがダウンロードできます。
書式:ADD
dest,src
SUB
dest,src
簡単に言うとADDは足し算,SUBは引き算です。サンプルプログラムを見るだけでも分かると思いますが、dest±srcです(ハショりすぎw)。演算の結果をdestに転送します。
何か、MOVで説明しなかったような気がするので一応遅補足しておくと、destはdestination operand, srcはsource operandのことです。Operandっていうのは演算の対象となるデータのことですね。
00401000 >/$ B8
01000000 MOV EAX,1
; EAXに1を転送
00401005 |. 05 FFFF0000 ADD EAX,0FFFF
; EAXにFFFFを転送
0040100A |. 66:83E8 01 SUB AX,1 ; AXから1引く
0040100E |. 04 01
ADD AL,1
; ALに1加える
00401010 |. A3 00304000 MOV DWORD PTR
DS:[403000],EAX ; メモリの403000にEAXを転送
00401015 |. 2905 00304000 SUB DWORD PTR DS:[403000],EAX ; メモリの403000からEAXを引く
0040101B |. 6A 00
PUSH 0
; /ExitCode =
0
0040101D \. E8 00000000 CALL
<JMP.&kernel32.ExitProcess> ; \ExitProcess
サンプルの説明は特に必要無いでしょう。分からなかったらBBSで質問して下さい。実行時は2の補数を念頭に入れて追ってみるといいかと思います(そういう風に作ったので)。
○INCとDEC
書式:INC dest
DEC
dest
destの値を1足す,あるいは1引くという意味です。どっちが、までは説明するまでも無いと思いますが、C言語の++と--に相当します。ハイ、必要ない気もしますが一応サンプルプログラムです。
00401000 >/$ B8
00000000 MOV EAX,0
; 初期化
00401005 |. 40
INC EAX
; EAXに1加える
00401006 |. 66:48
DEC AX
; AXから1引く
00401008 |. FEC4
INC AH
;
AHに1加える
0040100A |. 48
DEC EAX
; EAXから1引く
0040100B |. FECC
DEC AH ;
AHから1引く
0040100D |. 6A 00
PUSH 0 ; /ExitCode = 0
0040100F \. E8 00000000 CALL
<JMP.&kernel32.ExitProcess> ; \ExitProcess
これも特に説明の必要はないですねw
○MULとIMUL
書式:MUL src
IMUL
src
IMUL dest,src
IMUL dest,src1,src2
掛け算です。アセンブラの乗除は複雑です。何故なら、扱うビットをまず超えてしまうためです。100×100=10000で桁が全然違うことを考えれば当たり前ですね。従って演算結果を転送する領域に注意が必要になります。与太話はこれくらいにして実際にそれぞれの説明に入ります。
MUL srcはsrcによって転送する領域が変わります。それぞれ
|
srcが8ビット (BYTEサイズ) |
src とALの乗算結果をAXレジスタに転送 |
|
srcが16ビット (WORDサイズ) |
src とAXの乗算結果の上位16ビットをDXに、下位16ビットをAXレジスタに転送 (二つのレジスタにより32ビットを表現する) |
|
srcが32ビット (DWORDサイズ) |
src とEAXの乗算結果の上位32ビットをEDXに、下位32ビットをEAXレジスタに転送 (二つのレジスタにより64ビットを表現する) |
IMUL srcはMULと同じです。
IMUL
dest,srcはdestとsrcの乗算結果をdestに転送します。destはレジスタでなければなりません。srcはレジスタでもメモリ参照でも数値でもOKです。
IMUL
dest,src1,src2はいい加減予想もつきそうですが、src1とsrc2の乗算結果をdestに転送します。destはレジスタ,src1はレジスタまたはメモリ参照,src2は数値が入ります。
00401000 >/$ B8
68243412 MOV
EAX,12342468
00401005 |. BA 78563412 MOV
EDX,12345678
0040100A |. F6E2
MUL DL
; 78×68をAXに
0040100C |. 66:F7E2 MUL
DX ; 5678×30C0をAX:DXに
0040100F |. BA 78563412 MOV
EDX,12345678
00401014 |. F7EA
IMUL EDX
; 12345678×12345A00をEDX:EAXに
00401016 |. B8 00500000 MOV
EAX,5000
0040101B |. BA 33330000 MOV
EDX,3333
00401020 |. 0FAFC2
IMUL EAX,EDX ; 3333×5000をEAXに
00401023 |. 69C2 66660000 IMUL EAX,EDX,6666
; 3333×6666をEAXに
00401029 |. 6A 00
PUSH 0
; /ExitCode =
0
0040102B \. E8 00000000 CALL
<JMP.&kernel32.ExitProcess> ; \ExitProcess
まぁあまり見ないのでそれほど気にしなくてもいい気もしますw
書式:DIV src
IDIV src
ハイ、もちろん割り算です。またもやsrcのサイズに応じて計算結果を転送します。
ちなみにDIVとIDIVで挙動は同じです。srcにはレジスタかメモリ参照が入ります。
|
srcが8ビット (BYTEサイズ) |
AHを上位8ビット,ALを下位8ビットとする全部で16ビット(つまりAXのこと)をsrc で除し(AH:AL/src=AX/src)、商をALに,余りをAHレジスタに転送 |
|
srcが16ビット (WORDサイズ) |
DXを上位16ビット,AXを下位16ビットとする全部で32ビット(つまりDX:AX)をsrc で除し(DX:AX /src)、商をAXに,余りをDXレジスタに転送 |
|
srcが32ビット (DWORDサイズ) |
EDXを上位32ビット,EAXを下位32ビットとする全部で64ビット(つまりEDX:EAX)をsrc で除し(EDX:EAX /src)、商をEAXに,余りをEDXレジスタに転送 |
略して書くとこんな感じです。
|
srcのサイズ |
演算処理 |
商 |
余り |
|
BYTE |
AH:AL/src |
|
AH |
|
WORD |
DX:AX/src |
AX |
DX |
|
DWORD |
EDX:EAX/src |
EAX |
EDX |
ちなみにsrcに0を与えるとエラーになります。また、商や余りがその持つ領域を超えるような場合もエラーになります。例えば1010÷10=101…0ですね。これはsrcがBYTEサイズなので商・余りもBYTEサイズでないといけませんが、101はWORDサイズの領域が必要になります。従ってエラーです。まぁ「余り小さい数で割らないようにしよう=srcを余り小さくしない」ということです。
00401000 >/$ B4
12
MOV AH,12
00401002 |. B0 34 MOV
00401004 |. B2 20
MOV DL,20
00401006 |. F6F2
DIV DL ;
1234/20=91…14
00401008 |. B8 78560000 MOV
EAX,5678
0040100D |. BA 34120000 MOV
EDX,1234
00401012 |. C705 00304000 >MOV DWORD PTR
DS:[403000],4321 ; 12345678/4321=456C…1F8C
0040101C |. 66:F735 003040>DIV WORD PTR
DS:[403000]
00401023 |. B8 F0DEBC9A MOV
EAX,9ABCDEF0
00401028 |. BA 78563412 MOV
EDX,12345678
0040102D |. C705 00304000 >MOV DWORD PTR
DS:[403000],98765432
00401037 |. F735 00304000 DIV DWORD PTR DS:[403000]
; 123456789ABCDEF0/98765432=1E9131AB…91430F8A
0040103D |. 6A 00
PUSH 0 ; /ExitCode = 0
0040103F \. E8 00000000 CALL
<JMP.&kernel32.ExitProcess>
;
\ExitProcess
と言うことで、第二回はアセンブラの四則演算でした。本当は主要なニーモニック全部説明しようかとも思ったのですが冗長的になりそうだったので。第三回では他のニーモニックの説明を完結させたいと思いますが、わたしのモチベーションによっては第四回まで伸びるかも・・・^^;
なお、ニーモニックが終わったらいよいよAPIの登場です。
サンプルプログラムの著作権とかは面倒なので放棄してます。好きに使ってもらって構いません。