x86なCPUについて
アセンブラはCPUに非常に近い言語であるので、アセンブラの解説を始める前にCPUを理解しておくのが賢明だろう。
x86なCPUとは8086互換のCPUのことである。例えばPentiumやAthlonなどはx86なCPUだ。
レジスタ
CPUは主にデータの計算を行う回路だ(他にもする仕事はあるけどね)。データを二つ受け取りそのデータを加工する(足したり、引いたり、いろいろ)。その入力データと出力データを保存するためにメモリが必要になる。
8086では効率化のためにCPU内部に下記に示す計算専用の特殊なメモリを用意してある。これをレジスタとよぶ。
汎用レジスタ | AX | AH |
AL | ||
BX | BH | |
BL | ||
CX | CH | |
CL | ||
DX | DH | |
DL | ||
インデックスレジスタ | SI | |
DI | ||
特殊レジスタ | BP | |
SP | ||
IP | ||
セグメントレジスタ | CS | |
DS | ||
ES | ||
SS | ||
フラグレジスタ |
さらに32bitCPUではそれぞれのレジスタが32bitに拡張されている。例えばEAXは下記の用になっている
EAX | AX | AH |
AL | ||
. . |
レジスタの使い方
レジスタはどれもほとんど同じように扱えるが、一応それぞれ利用目的が決まっている。
汎用レジスタは汎用に使えて計算などに用いる。インデックスはよく分からないがとくに意識する必要はない(と思うw)。特殊レジスタはスタックで使用される、初期設定以外でこのレジスタを直接いじる事はあまり無い。セグメントレジスタはメモリアドレスに関係していて下で詳しく述べる。フラグレジスタは1か0を表すレジスタで例えば、引き算の結果が0になったら0フラグが立つ。これを利用して、分岐などを行うことができる。
レジスタはC言語に置ける変数の様に簡単に扱える。
たとえばアセンブラで
mov ax, 1 mov bx, 2 add ax, bx
はC言語の下記に相当する
ax = 1; bx = 2; ax += bx;
メモリアドレスについて
8086ではメモリアドレスの指定に二つのレジスタを使用する。一つのレジスタでは16bitの範囲(0x0000〜0xFFFF)しか指定できないので。それにセグメントレジスタの値を16倍して加算することで1MBの範囲を指定できるようになっている(32bitCPUでは4GBまでの範囲が扱える)。
例えばメモリアドレス0x1FFFFのデータをBXへ代入したい場合、セグメントレジスタDXに0x1000を代入し下記のように書く
mov ax, 0xFFFF mov dx, 0x1000 mov bx, [dx:ax] ; 0x1000×16+0xFFFF=0x1FFFF
dxは自動的にに加算されるのでここでdx:は省略可能である
mov bx, [ax]
つまりdxの値は慎重に設定すべきである