アドレッシング
メモリとのデータの転送
以前、MOV命令でレジスタに即値を代入するなどの処理を行いました
今回は、これにメモリも加えてオフセットアドレスでのメモリへの転送も覚えましょう
指定した16進数値やレジスタの内容がオフセットアドレスであることを明示するには [ ] を使います
レジスタの場合は、[BX] というように指定すると
BX レジスタの内容がオフセットアドレスと解釈されます
定数で直接オフセットアドレスを指定するには、[0F00] というように16進数で指定します
MOV AX , [0200]
MOV [0200] , AX
上は、オフセットアドレス 200h の内容をレジスタへ代入し
下は、AXレジスタの内容をオフセットアドレス 200h へ代入しています
さて、これまでレジスタへのデータへの転送などを高水準言語にちなんで「代入」と表現しましたが
アセンブリ言語では、他の記憶媒体からデータを読み込むことをロードと呼び
レジスタからメモリへデータを転送することを、特別にストアと呼んでいます
//メモリから、他の記録媒体への保存はご存知「セーブ」と言います
ちなみに、同じ記録媒体の別アドレスへデータを写す時は転送すると表現します
次のプログラムは、メモリとレジスタ間のロードやストアを行うプログラムです
-A 100
15F2:0100 MOV AX , 4142
15F2:0103 MOV [0200] , AX
15F2:0106
-G =100 106
AX=4142 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000
DS=15F2 ES=15F2 SS=15F2 CS=15F2 IP=0106 NV UP EI PL NZ NA PO NC
15F2:0106 02FF ADD BH,BH
-D 200 201
15F2:0200 42 41 BA
レジスタ、AXのデータをメモリにストアしているのがわかります
正しくストアされているかを調べるため、メモリをダンプした結果はご覧の通りです
さらに、次のプログラムはストアしたデータを、再び DX レジスタにロードしています
このように、右辺のオペランドにオフセットアドレスを指定することも可能です
-A 100
15F2:0100 MOV AX , 4142
15F2:0103 MOV [0200] , AX
15F2:0106 MOV DX , [0200]
即値のストア
メモリへレジスタのデータをストアすることは、上のプログラムでできましたが
実は、即値をメモリへストアする時はもう少し工夫が必要です
数値を直接ストアする場合、データのサイズを指定しなければだめなのです
これは、メモリは1バイトでも1ワードでも受け入れることができるためです
レジスタは、受け取るレジスタによってサイズが決定されます
しかし、メモリはストアする時に1バイトのメモリを対象とするか1ワードとするかわからないのです
そこで、明示的にメモリのサイズを指定するのが PTR 演算子です
この演算子はアセンブラにサイズを知らせるためのものです
SIZE PTR
SIZEには、BYTE または WORD を指定します(32ビット環境では、DWORDもある)
BYTEを指定した場合は1バイト、WORDを指定した時は2バイト(16ビット)確保します
構文的な仕様は、アセンブラによって異なりますが一般的に左辺のオペランドの前に指定します
MOV BYTE PTR ...
このようにすれば、1バイトのメモリを対象にしたストアを明示します
ほとんどのアセンブラでは、メモリに即値をストアする場合に指定しなければいけません
-A 100
15F2:0100 MOV BYTE PTR [0200] , 41
15F2:0105 MOV WORD PTR [0300] , 4342
15F2:010B
これを実行し、メモリダンプを行うと次のようになっています
-D 200 200
15F2:0200 41 A
-D 300 301
15F2:0300 42 43 BC
周辺の値も調べて、正しいサイズで行われているか調べるのもよいでしょう
このように、即値をストアすることができるということも重要なことです
アドレッシングモード
最後に、簡単な注意点ですが重要なので説明しますが
データの転送には、左辺と右辺のオペランドの関係は機械語で一意です
つまり、MOV AX , FF と MOV AX , [0200] では、機械語レベルでは違う存在です
アセンブラは、左辺と右辺のタイプ(レジスタ、メモリ、即値)で機械語を決定します
このとき、構文的に正しければ全て良しという高水準言語の考えは通用しません
どういうことかというと、次のような場合を考えてください
MOV [0200] , [0300]
これは、オフセットアドレス 300h から 200h へのデータの転送を意味しますね
これまでの MOV を考えれば、構文的にも正しく思えます
しかし、これに対する機械語はないのです
このような場合、アセンブラはそれをサポートしません(マクロアセンブラは例外)
アセンブラでは、レジスタ、メモリ、即値のうち、転送可能な組み合わせが決まっています
この関係をアドレッシングモードと呼びます
//レジスタでも、命令により使えるレジスタと使えないレジスタに分別できる
即値
|
---|
↓ | | ↓
|
---|
レジスタ AX , BX , CX , DX SI , DI , BP , SP | ----> | メモリ (セグメント : オフセット)
|
---|
<----
|
---|
↑↓ | | ↑↓
|
---|
セグメントレジスタ CS , DS , ES , SS
|
---|
MOVのアドレッシングモード
|
---|
矢印は、転送可能なデータの関係です
たとえば、セグメントレジスタにはレジスタやメモリのデータをロードできますが
即値を直接ロードさせることはできません
ただし、レジスタは特別でレジスタどうしの転送が可能です
フラグレジスタは特殊なレジスタなので、一切の転送を行えません