保存する場所に番地(アドレス)をつけ、そこに1バイトずつデータを保存する。番地は普通、通し番号だが1バイトでは0番地から255番地までの256しか表現できない。2バイトあれば256×256で65536まで表現できる。これが64KBのメモリである。1980年あたりではこの大きさのメモリを扱うCPUが主流であった。次の表は、この64KBのメモリのうち、53248番地からのメモリにデータが入っている様子をイメージしたものである。
番地(アドレス) (2バイトの場合) |
データ (1バイト) |
---|---|
1101000000000000 | 01011110 |
1101000000000001 | 00100011 |
1101000000000010 | 01010110 |
1101000000000011 | 11110011 |
1101000000000100 | 00111110 |
1101000000000101 | 11111110 |
1101000000000110 | 11010011 |
1101000000000111 | 01110001 |
1101000000001000 | 11001101 |
1101000000001001 | 01110010 |
1101000000001010 | 01100001 |
2013年現在PCのメモリは4GB(=4000000KB)あたりが普通になっているのでもちろん2バイトでは足りない。
コンピュータはこれでいいのだが、人間はさすがに1と0が詰まっていると読みにくい。そこで4ビットごとに区切ってみる。
番地(アドレス) | データ |
---|---|
1101 0000 0000 0000 | 0101 1110 |
1101 0000 0000 0001 | 0010 0011 |
1101 0000 0000 0010 | 0101 0110 |
1101 0000 0000 0011 | 1111 0011 |
1101 0000 0000 0100 | 0011 1110 |
1101 0000 0000 0101 | 1111 1110 |
1101 0000 0000 0110 | 1101 0011 |
1101 0000 0000 0111 | 0111 0001 |
1101 0000 0000 1000 | 1100 1101 |
1101 0000 0000 1001 | 0111 0010 |
1101 0000 0000 1010 | 0110 0001 |
パターン | 記号 |
---|---|
0000 | 0 |
0001 | 1 |
0010 | 2 |
0011 | 3 |
0100 | 4 |
0101 | 5 |
0110 | 6 |
0111 | 7 |
1000 | 8 |
1001 | 9 |
1010 | A |
1011 | B |
1100 | C |
1101 | D |
1110 | E |
1111 | F |
区切ったものは16種類のパターンになるので、0,1,2,…,E,F の16個の記号で表してみる。(要するに16進表現)
番地(アドレス) (2バイトの場合) |
データ (1バイト) |
---|---|
D000 | 5E |
D001 | 23 |
D002 | 56 |
D003 | F3 |
D004 | 3E |
D005 | FE |
D006 | D3 |
D007 | 71 |
D008 | CD |
D009 | 72 |
D00A | 61 |
かなり見やすくなった。たとえば00111110のパターンを探すのは大変だが、3Eを探すのはそう面倒ではない。
細長くなって場所を取るので、以下のように1行に16個ずつ書くこともよくある。たとえば、
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | |
D000 | 5E 23 56 F3 3E FE D3 71 CD 61 72 3E FF D3 71 FB |
D010 | 00 00 00 00 00 00 00 00 00 00 00 00 13 13 13 13 |
D020 | D9 0E 02 06 08 D9 0E 02 D5 E1 06 08 CB 06 1F 23 |
D030 | 23 10 F9 CD D4 3E 0D 20 F1 D9 10 E9 D9 13 D9 0D |
D040 | 20 E1 D9 C9 |
この場合、D000行の04列目は、番地はD004、データは3Eとよむ。
訂正をしています下記の訂正箇所をご覧ください。
実は上記のメモリに格納されていたのは機械語のプログラムである。
メモリに入れるのはプログラムの実行で作成されるデータばかりでなくプログラムそのものもメモリに配置する場合が多い(そうしない方法もある)。
この例ではCPUはD000から実行するようにセットされ(これもプログラムによってセットされるのだが)、まず5Eという命令を実行する。
後はその命令に書かれているとおり作業を進めていく。普通は次の番地の命令に進むが、場合によってはいくつかの命令を飛び越したり、戻ったりもする。
この例では最後付近のD043のC9でD000から作業を始めさせたプログラムにもどる。
訂正をしています下記の訂正箇所をご覧ください。
番地 | 命令 | ニーモニック |
D000 | 5E | LD E,(HL) |
D001 | 23 | INC HL |
D002 | 56 | LD D,(HL) |
D003 | F3 | DI |
D004 | 3E FE | LD A,FE |
D006 | D3 71 | OUT (71),A |
D008 | CD 7261 | CALL 7261 |
D00B | 3E FF | LD A,FF |
D00D | D3 71 | OUT (71),A |
D00F | FB | EI |
D010 | 00 | NOP |
... | .. | .. |
D01B | 00 | NOP |
D01C | 13 | INC DE |
D01D | 13 | INC DE |
D01E | 13 | INC DE |
D01F | 13 | INC DE |
D020 | D9 | EXX |
D021 | 0E 02 | LD C,02 |
D023 | 06 08 | LD B,08 |
D025 | D9 | EXX |
D026 | 0E 02 | LD C,02 |
D028 | D5 | PUSH DE |
D029 | E1 | POP HL |
D02A | 06 08 | LD B,08 |
D02C | CB 06 | RLC (HL) |
D02E | 1F | RRA |
D02F | 23 | INC HL |
D030 | 23 | INC HL |
D031 | 10 F9 | DJNZ D02C |
D033 | CD 3ED4 | CALL 3ED4 |
D036 | 0D | DEC C |
D037 | 20 F1 | JR NZ,D02A |
D039 | D9 | EXX |
D03A | 10 E9 | DJNZ D025 |
D03C | D9 | EXX |
D03D | 13 | INC DE |
D03E | D9 | EXX |
D03F | 0D | DEC C |
D040 | 20 E1 | JR NZ,D023 |
D042 | D9 | EXX |
D043 | C9 | RET |
CPUは命令と書いてあるパターンで作業するが、人間にはこれはきついので、それぞれどのような命令かを短く書いたものがニーモニックと呼ばれるものである。これならば少し楽になる。
ニーモニックはプログラミング言語ではありません。単にわかりやすい記号にしたものです。
LD | load | データの転送 |
INC | increase | 1増やす |
OUT | out put | 出力 |
JR | jump relative | 相対ジャンプ |
RET | return | 戻る |
NOP | no operation | なにもしない |
CALL | call | 他のアドレスにあるプログラムを呼び出して実行する |
CPU内部にあり、データを加算したり一時保存したりする場所。z80の場合はAF,BC,DE,HLがもう一セットあり、切り替えることができました。上で出てくる EXX命令は、AFをそのままに、BC,DE,HL を一度に別のセットに切り替えるものです。
7 0 | 7 0 |
A | F |
B | C |
D | E |
H | L |
IX | |
IY | |
PC | |
SP |
このレジスタの数と機能もCPUによりまちまちです。
上記の例は、z80というCPUのものです。
命令の意味するところも、ニーモニックの書き方もそれぞれ違います。
このプログラムの時代はz80の所属する86系と68系という2つの大きな流れがありました。それぞれの国に生まれた人は他国のCPUのプログラムはわからないというのが普通でした。
z80の元になったのは8080というインテル社のCPUで、これはその後、8086, 80186, 80286, 80386, i486, Pentium と製品が続き現在のPC用CPUの主流をなしています。
初めてこのページを見る方には、読む必要の無いものです。以前と違うじゃないかという方へのお詫びです。
1行に16個ずつ書いたメモリへの格納状況の表
(1) 以前は12個の00が抜けてその部分以降アドレスがずれてしまい、D043のC9などとの説明に合いませんでした。
(2) CALL NNMM の目的地のアドレスは上位バイトと下位バイトが バイトの並びと ニーモニックで逆になります。格納状況をプログラムリストから作った時に直していませんでした。正しく書き直しました。
機械語のプログラムの例
(1) こちらも00のNOPが抜けていました。しかし、NOPは何もしない命令ですし、アドレスごと抜けていたのでアドレスのずれはなく、プログラムの内容には関わらない間違いでした。
(2) D02Cの RLC (HL) は EXX と誤記していました。Z80の拡張命令で8080用のディスアセンブラが解釈できなかったものを手作業で直して間違いが生じました。CB 06 1F の並びは正しかったのですがニーモニックが間違っていました。
次の並びは間違いではありません
D008 CD 7261 CALL 7261 ;CD 61 72 に対して D033 CD 3ED4 CALL 3ED4 ;CD D4 3E に対して
この記法はNECのPC-8801のモニタについていた逆アセンブラの表記に合わせたものです。
7261は漢字ROMからフォントデータを読み出すルーチン、3ED4は1バイトをプリンタに出力するルーチンの開始アドレスです。
この逆アセンブラのニーモニックは8080用のものでした。LDはMOV、INCはINXなどと表記されました。Z80の拡張であるEXXやRLC (HL)は、???と表記されていました。
このプログラムはPC-8801を所有していた時に自作したもの(1983)ですが、機械語のプログラムの例として教材化した時に???では説明のしようがないのでZ80の表記に全面的に書き換えたのです。教材化の時にはすでに実機がなく紙の出力から起こしたためにいろいろ間違いを発生させました。ニーモニックの雰囲気を味わえれば問題ないのですが、思い入れのあるプログラムだったので、いまさらですが訂正させていただきました。