入社 2 年目のとき、まだセキュリティをやっていた頃にお世話になった本。本当に基本的な内容*1ではあるが、手を動かす演習が多かった*2こともあり、すごくわかりやすかった記憶がある。これがあったから、Java の仮想マシンの仕組みもよくわかった。
この週末、久方ぶりに読んだので、骨格だけメモしておく。
- 作者: 蒲地輝尚,水越康博
- 出版社/メーカー: アスキー
- 発売日: 2004/07/01
- メディア: 単行本
- 購入: 21人 クリック: 2,328回
- この商品を含むブログ (26件) を見る
アセンブリ言語全般
- セグメントアドレスとオフセットアドレス
- セグメントアドレス:アドレスを指すための基準点。セグメントベース
- オフセットアドレス:セグメントベースから、相対的にアドレスを指定
レジスタの種類
EIP と ESP
- EIP(インストラクションポインタ)
- ESP(スタックポインタ)
- スタックの一番上に積まれているアドレスを指す(アドレスの高い方から低い方へ進む)
- データの出し入れは、1 ワード(2 バイト)or ダブルワード(4 バイト)ずつ。オペランドのサイズに依存する
インストラクションセット(命令群)
(1) データ転送命令
; 1 バイトのデータ 5F を、AL レジスタにロードする MOV AL, 5FH
; EBX レジスタでオフセットアドレスを指定したメモリに、EAX レジスタの内容をストアする MOV [EBX], EAX
; EBX レジスタの内容 + 5 をオフセットアドレスとするメモリの内容を、EAX レジスタにロードする MOV EAX, [EBX+5]
(2) 算術演算命令
四則演算、論理演算(CPU 内部の演算ユニットに転送される)を実行する。演算が実行された後の状態が、フラグレジスタにセットされる。
- 加算・減算命令
- ADD, SUB
- INC, DEC(インクリメント, デクリメント)
; EAX レジスタに、00000005(4 バイト)を加える。演算結果は、EAX レジスタ転送される ADD EAX, 00000005H
- 比較命令
- CMP(コンペア):演算は引き算と同じ(ただし、演算結果は捨てられる)。演算結果の状態が、「フラグ」レジスタにセットされる
- 乗除算命令
; AX レジスタの内容を、BL レジスタの内容で割り、商を AL レジスタに、余りを AH レジスタにセットする DIV BL
- PTR 演算子
- 加減算では、使用するレジスタによって、対象のメモリが、バイト、ワード、ダブルワードかわかった。しかし、インクリメント、デクリメント、乗除算の場合などに、どのメモリを対象とするかがわからない。そこで、バイト、ワード、ダブルワードを指定する
- BYTE PTR <アドレス指定>
- WORD PTR <アドレス指定>
- DWORD PTR <アドレス指定>
- 加減算では、使用するレジスタによって、対象のメモリが、バイト、ワード、ダブルワードかわかった。しかし、インクリメント、デクリメント、乗除算の場合などに、どのメモリを対象とするかがわからない。そこで、バイト、ワード、ダブルワードを指定する
; レジスタ EBX の値が示すメモリを、ダブルワードのデータとしてインクリメント INC DWORD PTR [EBX]
(3) ジャンプ命令
- 無条件ジャンプ
- 条件ジャンプ(比較した値が符号なしの 4 バイトデータ)
- JE(Jump if Equal)
- JNE(Jump if Not Equal)
- JA(Jump if Above)
- JAE(Jump if Above or Equal)
- JB(Jump if Below)
- JBE(Jump if Below or Equal)
- 条件ジャンプ(比較した値が符号ありの 4 バイトデータ)
- JG(Jump if Greater)
- JGE(Jump if Greater or Equal)
- JL(Jump if Less)
- JLE(Jump if Less or Equal)
(4) スタックのプッシュ・ポップ
; ESP を 4 減らし、その値をオフセットアドレスとするスタック領域に、EAX レジスタの内容を退避する PUSH EAX
; ESP の値をオフセットアドレスとするスタック領域から、EAX レジスタにダブルワードデータを復帰し、ESP に 4 を加える POP EAX
; ESP を 4 減らし、その値をオフセットアドレスとするスタック領域に、EFLAGS レジスタの内容を退避する PUSHFD
; ESP の値をオフセットアドレスとするスタック領域から、EFLAGS レジスタにダブルワードデータを復帰し、ESP に 4 を加える POPFD
(5) サブルーチンのコール/リターン
スタックにより実現する。ネスト(入れ子構造)ができる。
- コール
- CAL <アドレス指定>
- アドレス指定の方法は、ラベル(名前:)or 変数名 or レジスタ
- CAL <アドレス指定>
- リターン
- RET
- コール命令で、メインルーチンからサブルーチンへ
- EAX レジスタと EDX レジスタの内容を、スタックエリアに退避
- サブルーチンの中で EAX と EDX レジスタを使う
- 退避していた EAX や EDX レジスタの内容をもとに復帰
- リターン命令でサブルーチンからメインルーチンに戻る
- スタックにプッシュしていた内容を EIP にロード
CALL SomeSubroutine ... SomeSubroutine: ... RET
(6) 論理演算命令
OR, AND, XOR など。
; AL レジスタと、1 バイトのデータ 5F の AND をとり、結果を AL レジスタに残す AND AL 5FH
(7) ローテート/シフト命令
右または左に 1 ビットずらす命令。
- ローテート:押し出されたビットを、反対側の空いたビットに返す(円環のよう)。スルーキャリーは、キャリーフラグの内容が、空いたビットに入る。押し出されたビットがキャリーフラグに入る
- 左ローテート:RCL(Rotate Left through Carry), ROL(ROtate Left)
- 右ローテート:RCR(Rotate Right through Carry), ROR(ROtate Right)
- シフト:押し出されたままずらす。算術シフトは、ビットパターンを符号つきの数値ととらえる(シフトしても符号が変わらないようにする)
- 左シフト:SHL(SHift logical Left), SAL(Shift Arithmetic Left)
- 右シフト:SHR(SHift logical Right), SAR(Shift Arithmetic Right)
; BL レジスタの内容を、CL レジスタで指定する回数だけ、右にローテートする ROR BL, CL