アセンブリ言語関連の内容を扱います。
NASM アセンブラ、つまり x86 CPU のプログラムです。
アセンブリ言語で書かれたソースをアセンブルしたい:
nasm -f bin source.asm -o program.bin
source.asm というソースをアセンブルし、
program.bin というファイル名で機械語のコードを出力します。
このとき得られるコードは 16 ビット用のコードで、
機械語だけを単純に出力しているプレーンなバイナリファイルです。
こうして出来上がったバイナリファイルを調べれば、
機械語のコードが読める、というわけです。
しかし、ディスアセンブラ (ndisasm) を使えば、
バイナリファイルの機械語とアセンブラコードの対応付けも
行ってくれます。
機械語のディスアセンブル:
ndisasm program.bin
簡単な命令1つだけの解析。
アセンブルソース:
mov ax, 0x1122
ディスアセンブル結果:
00000000 B82211 mov ax,0x1122
この B8, 22, 11 (それぞれ16進数)という3バイトのデータが
mov ax, 0x1122 という命令に対応していると考えられます。
こんな感じでアセンブリ言語の命令の機械語を調べることが可能です。
nop命令とは、何もしない命令です。
ソース:
nop
ディスアセンブル:
00000000 90 nop
これによると、nop命令は1バイト、0x90というコードだと推測。
jmp命令とは、命令の実行位置を指定の場所までジャンプする命令です。
ソース:
hang: jmp hang
hang: というのはラベルです。
これによりラベルの位置までジャンプします。
この場合だと、同じところを永遠にループします。
ディスアセンブル:
00000000 EBFE jmp short 0x0
ジャンプ先を様々に変えてみよう:
jmp label nop nop nop nop label:
ディスアセンブル:
00000000 EB04 jmp short 0x6 00000002 90 nop 00000003 90 nop 00000004 90 nop 00000005 90 nop
db, dw, dd などの疑似命令を使えば、
直接バイトデータを書くことが可能です。
例:
db 0x11, 0x22 dw 0x3344 dd 0xaabbccdd
db は1バイト、dw は2バイト、dd は4バイトのデータです。
ラベルはメモリの番地を参照するのに使用する名前と考えられます。
このラベルをソース中に使うこともできます:
mov ax, label jmp label label: nop nop nop nop
ディスアセンブル:
00000000 B80500 mov ax,0x5 00000003 EB00 jmp short 0x5 00000005 90 nop 00000006 90 nop 00000007 90 nop 00000008 90 nop
このようにラベルの値を使うことも可能です。
org ディレクティブとは、ロードされるメモリの番地を指示する
指示子(ディレクティブ)です。
これを指定するとメモリ番地が変わる? のかどうか調べます。
ソースは先ほどのものと同様です:
org 0x100 mov ax, label jmp label label: nop nop nop nop
先頭に org 0x100 が付いていること以外、
以前のものと同様です。
これをディスアセンブルしてみます:
00000000 B80501 mov ax,0x105 00000003 EB00 jmp short 0x5 00000005 90 nop 00000006 90 nop 00000007 90 nop 00000008 90 nop
"mov ax, label" の部分のラベル番地が変化しているようですが、
"jmp label" の方は変化していませんね。
こちらを見たほうがいいかもしれません。