アセンブリ言語の基礎知識 Part 3

●アセンブリ言語の表記

 機械語の解説をしてきましたが、コードやデータの集まりですから当然、こんなのがたくさん並んだら、見るのが大変ですし、人間にはわかりにくいですよね。
 そこで、CPUメーカーさんが仕様書になかに、ニーモニックと呼ばれる表記法を作っています。これは機械語の動作を人間がわかりやすいようにするためのもので、それを使った言語がアセンブリ言語です。
 当然このニーモニックはメーカーがCPU用のものを作りますからにそれぞれ違いますので注意が必要です。(ニーモニックはメーカーの著作物であり同じ表記だと著作権の問題になるため同じになることはまず無いです)

 さてZ80命令の仕様書には次のようなニーモニックが記載されています。  

CPU命令仕様
コード オペレーション ニーモニック
00h Non OP NOP
3Eh A ← n LD A,n
80h A ← A+B ADD A,B
 

 さて、このニーモニックという部分がアセンブリ言語での表記法です。このLD A,nでAレジスタにnで指定した値を入れる動作をCPUにさせる命令を表します。
 機械語表記をニーモニックを使ってアセンブリ言語に書き換えてみましょう。  

機械語とアセンブリ言語の対応
番地 データ アセンブリ言語
0000h 00h NOP
0001h 3Eh LD A,10h
0002h 10h


 
 
足し算プログラムのアセンブリ表記
番地 データ アセンブリ言語
0000h 3Eh LD A,10
0001h 0Ah
0002h 06h LD B,20
0003h 16h
0004h 80h ADD A,B

 アセンブリの表記法を説明しましたので、ここからは、アセンブリ言語の記述で説明してきます。

 まずいくつかの命令を紹介ながら、実際の仕様書の読み方も説明しましょう。  

ニーモニック仕様
ニーモニック オペレーション
LD r,n r ← n
LD r,r' r ← r'
ADD A,r A ← A+r
LD rr,nn rr ← nn

 さて、いきなりなんだか暗号のようになってますけど、小文字のrとかr' などはレジスタを表す文字を書きなさいってことを意味しています。
 この表から言えば、
   LD r,n
の表記法を使って、
   LD A,2Eh
   LD B,52h
といったようなアセンブリが組めるわけです。
 表からも分かりますが、r,n となったら左(n)から右(r)へ移動する基本です。

 表の2行目のLD r,r' も同様に
   LD A,B
 といったようにレジスタ同士を指定することでレジスタ間の移動が行えます。

 さて、表の2行目までは移動命令でした。3行目は演算命令となります。
これはAレジスタとrレジスタに保存されている値を加算しその結果をAレジスタに格納するという命令を実行します。
 これら以上からたとえば、
   LD A,2Eh
   LD B,52h
   ADD A,B
 と記述すれば、Aレジスタに2Ehの値を入れ、Bレジスタに52hの値を入れる。それてA,Bレジスタの値を加算し、アキュムレータへ保存という動作を行うわけです。

 最後に
   LD rr,nn
 というのがあります。これはレジスタの説明でBC、DE、HLはそれぞれ2つのレジスタを繋げて16ビットとして扱うことができるとお話ししました。このrrは繋げることが可能なレジスタを指定して、値を16ビット(2バイト)で扱うことができるものです。ですから
   LD HL,1234h

   LD H,12h
   LD L,34h
と同様の動作となるわけです。

●アセンブリ言語のメモリアクセス

 さて、ここまではアセンブリの予備知識でした。ここからがC言語に関わる重要な知識です。
まずは次の仕様を見てください。  

ニーモニック仕様
ニーモニック オペレーション
LD A,(nn) A ← (nn)
LD (nn),A (nn) ← A
 

 この( )でくくられている部分は「メモリとの転送」を意味する記述です。今まではレジスタ内部でのデータの転送が行われたわけですが、このように表記することでメモリへの格納や読み出しができます。
たとえば
    LD A,(0010h)
と表記した場合、メモリの0010h番地の値をAレジスタへ転送するという動作を表します。 逆も同様に
    LD (0010h),A
と表記すれば、Aレジスタの値をメモリの0010h番地へ転送するというものです。

 さてこれらは直接メモリのアドレスを( )の中で指定してメモリとCPUがデータのやりとりを行っています。この方法を「直接アドレス指定」とか「直接アドレッシング」と呼ばれます。  

ニーモニック仕様
ニーモニック オペレーション
LD r,(HL) r ← (HL)
LD (HL),r (HL) ← r
 

 今度はアドレスを指定する場所がレジスタになっています。 これはレジスタHLに格納されている値のメモリアドレスにある値と指定したレジスタrとの移動する命令となります。

たとえば
    LD HL,0010h
    LD A,(HL)
と表記した場合、0010hという値をHLレジスタへ転送し、そのHLレジスタが示す値のアドレスからAレジスタへ値を転送する。 逆も同様に
    LD (HL),A
と表記すれば、Aレジスタの値をメモリのHLレジスタの示す値のアドレスへ転送するというものです。

 今度は直接、()の中へ直接、メモリのアドレスを指定しないで、HLというレジスタを介して指定したメモリアドレスとCPUがデータのやりとりを行っています。この方法の場合を「間接アドレス指定」とか「間接アドレッシング」と呼ばれます。
 なぜ、このようにアドレスを指定するのにレジスタを介して行うのか。理由は簡単です。
 メモリ上に100バイトのデータが並んで格納されている場合、それを続けてCPUに読み込むという処理をするような場合、100回LD命令を書くより、HLへ先頭のアドレスを指定して、HLの値を+1しながら100回繰り返して読んだ方が効率的で、プログラムの大きさを考えても有効であることは言うまでも無いでしょう。

 そして、このような場合にHLレジスタのことを「ポインタ」と呼んでいます。このことは、C言語で登場するポインタとなんら変わりはありません。アドレスの値をレジスタに入れ、その値をポインタとしてアドレスを指定する(示す)、この間接アドレッシングをC言語で表現するものとして同じポインタという手法が使われるのです。