ポケコンうらわざ大事典 特別版 まえがき この文章は、1988年に名古屋大学教養部 S-32 クラスが作成した新入生 歓迎パンフレット(といっても1000ページ以上ある)「NUページ」のために書い た「ポケコンうらわざ大事典」と、同じく1988年から1990年頃にかけ て私のまわりで作っていた同人誌に掲載していた「ポケコンうらわざ大事典 part II」を再編集したものです。 注意 1:特に注のない限り「現在」は原稿が書かれた時点をさしています。 2:1995年現在では誤りとわかっていたり、不適等となっていることがら については削除または注をつけています。 3:元の文中にあった外字、98依存文字についてはできるだけ機種依存しな いように直しています。が、一部変な文字が残っている可能性はあります。な お JISX0201 カナについては表中もしくはプログラム中の場合はそのままにし てあります。 青木 充 名古屋大学理学部物理学科Nhe研(高エネルギー物理) Aoki Mitsuru mitsuru@hepl.phys.nagoya-u.ac.jp http://www.hepl.phys.nagoya-u.ac.jp/docs/mitsuru.html ポケコンうらわざ大事典 Part I まえがき(1988年) この記事は、ポケコンの魅力に取り付かれてしまった人や買ってはみたが電 卓としてしか使っていない人のための記事です。とは言っても一応この記事を 読むためにはBASICについての知識が必要です。ただ私はPC−1470 Uを含めたPC−12系のポケコンについては余りよく分からないこともある ので、特にマシン語のところについてはおかしなところもあるかも知れません がその辺はご勘弁をねがいます。また、この記事にあるサンプルプログラムに ついては、すべて動作確認する時間がありませんでしたので、ひょっとしたら うまく動かないプログラムがあるかも知れません。 ポケコン裏わざ大事典partII まえがき(1990年)  私が初めてポケコンというものを買ってから、もうすでに8年になります。 このあいだにもポケコンの進歩というものはめざましく、現在ではほとんどパ ソコンと変わらないぐらいの性能になりました。しかし、この世界は日進月歩 ではなくて秒進分歩だと言われるぐらい製品の発売サイクルが短いものです。 このような環境では、新製品の良いことにばかりに目がいってしまうのも当然 です。しかし、このようなことばかりしていて意味はあるのでしょうか。「上 を見ればきりがない、下を見れば何もない。」と言った人もいます。現在持っ ている機種よりも新製品の方が性能がいいのは当然です。だからといってどん どん新機種に買い換えていたのでは、お金がいくらあっても足りるものではな いでしょう。(ポケコンは安いので出来ないことはないけれども、一種のたと えだと思って下さい。)そんな無駄なことをするよりも、一つの機種を完全に ものにする、いってみれば「骨の髄までしゃぶる」ことが必要なのではないで しょうか。このポケコンうらわざ大事典は、皆さんのそのような要求を満たし てくれることでしょう。 第0部 PC-1470編(旧ポケコンうらわざ大事典 Part I) 第1章 ポケコンで電子独和辞典を作ろう さて、皆さんは英単語や独単語を覚えるときに何を使っているのでしょうか。 せっかくポケコンがあるのだからポケコンを使ってみませんか。というわけで、 ここでは独単語の表示方法について見ていきましょう。 1.1 GPRINT文の使い方 独単語を表示させようとするときに困った問題があります。それは、ウムラ ウトや が表示できないことです。そんなときに登場するのがGPRINTで す。GPRINT文は、一文字分だけですが、好きなキャラクターを表示させ ることができます。それでは次のように操作して下さい。   例:GPRINT "482B1F2B48" または GPRINT 72;43;31;43;72 いかがですか、たぶん人の形をしたキャラクタが表示されたと思います。こ の例でみて分かるようにGPRINTには2通りの方法があります。ひとつめ は16進数の文字列を使う方法です。ただこの場合。固定変数(A$,B$な どの1文字の変数)を使って、一文字分の表示することはできません。なぜな ら固定変数は7文字までと決まっているので、10文字必要なこの場合には、 不足なのです。このときには、単純変数(AA$,A1$など2文字の変数) か10文字以上とった配列変数を使って下さい。また、もう一つの方法は、数 値を使う方法です、ただこの方法では表示に時間がかかるので余りおすすめで きません。この方法の利点は、表示を変化させることができることです。次の プログラムを実行してみて下さい。 10:A=72:B=43:C=31:D=43:E=72: WAIT 0 : CLS : GPRINT A;B;C;D;E; 20:FOR I=1 TO 7:A(I)=A(I)/2: CURSOR 0: GPRINT A;B;C;D;E;: NEXT I 30:FOR I=1 TO 7:A(I)=A(I)*2: CURSOR 0: GPRINT A;B;C;D;E;: NEXT I 40:GOTO 20 1.2 GPRINTが嫌いなひとへ このように、自由にキャラクターを表示させるには、GPRINTを使うの が一番簡単なのですが、「私はGPRINTが嫌いだ!」とか、2文字以上表 示させたい人には別の方法があります。それは、POKE文を使って、VRA M(Video-RAM:画面表示用のメモリー)に直接書き込んでやる方法です。そ れでは次のプログラムを入力して下さい。 10:POKE &2800,&48,&2B,&1F,&2B,&48 20:GOTO 20 または 10:POKE &2800,73,43,31,43,72 20:GOTO 20 たぶん、先ほどと同じ結果になったと思います。PC−1470UのVRA Mの構成は、次のようになっています。12桁目のところでアドレスが変わる ことに注意して下さい。先ほどのGPRINT文と同じデータを使って表示さ せます。  画面表示用VRAM 0        11 12       23桁 一行目 | &2800〜&283B| &2A00〜&2A3B| 二行目 | &2840〜&287B| &2A40〜&2A7B|  モード表示用VRAM アドレス | Bit 7 | Bit 6| Bit 5| Bit 4| Bit 3| Bit 2| Bit 1| Bit 0 | 2^7=128 2^6=64 2^5=32 2^4=16 2^3=8 2^2=4 2^1=2 2^0=1 ----------+-------+-------+-------+-------+-------+-------+-------+------ &283C| | BATT | ( ) | HYP | AER | PRO | RUN | CAL ----------+-------+-------+-------+-------+-------+-------+-------+------ &283D| | | | | DBL | SHIFT | DEF | BUSY ----------+-------+-------+-------+-------+-------+-------+-------+------ &287C| | PRINT | STAT | MATRIX| G | RAD | M | E ----------+-------+-------+-------+-------+-------+-------+-------+------ &287D| | | | | DE | SML | 小 | カナ  このモード表示用VRAMも、画面表示用VRAMと同じようにPOKE文 でセットすることができます。また、このモード表示用VRAMをセットする ことにより、プログラムでカナモードにしたりSMLモードにすることもでき ます。また、三角関数の角度の単位もこのモード表示用のVRAMできまりま す。PROとRUNの両方をつけたときにはプログラムを消さないように注意 して下さい。   例:カナモードにする POKE &287D, PEEK &287D OR 1 DEGREEモードにする(DEとGをつける) POKE &287C,8,8  ところで次のプログラムを実行してみて下さい。 10:FOR I=&2800 TO &283D:POKE I,255:NEXT I 20:FOR I=&2840 TO &287D:POKE I,255:NEXT I 30:FOR I=&2A00 TO &2A3B:POKE I,255:NEXT I 40:FOR I=&2A40 TO &2A7B:POKE I,255:NEXT I 50:GOTO 50 画面が真っ黒になりましたね。これぞ「必殺電池消耗プログラム」です。オー トランにしておけばいたずら防止にもなります。 1.3 キャラクター作りを楽にする法。 GPRINTにしろPOKEにしろキャラクターを作るのは大変です。よく ある方法としては、方眼紙を塗りつぶしていくものがあります。しかし、せっ かくポケコンがあるですから、これもポケコンに任せてしまいましょう。とい うわけでキャラクター作成プログラムの登場です。次のプログラムを実行して 下さい。 10:"A" CLEAR : WAIT 0: CLS :X=1:Y=1: USING "####" 20:POKE &281D+X,A(X) XOR Y 30:CURSOR 24: PRINT HEX A; HEX B; HEX C; HEX D;HEX E; 40:POKE &281D+X,A(X) 50:I$= INKEY$ 60:IF I$="2" AND Y<64 LET Y=Y*2 70:IF I$="8" AND Y>1 LET Y=Y/2 80:IF I$="4" AND X>1 LET X=X-1 90:IF I$="6" AND X<5 LET X=X+1 100:IF I$= CHR$ 13 LET A(X)=A(X) XOR Y 110:IF I$="C" GOSUB 150 120:IF I$="R" GOSUB 200 130:IF I$="E" END 140:GOTO 20 150:INPUT "Copy chr. :";J$ 160:CLS 170:J$= LEFT$ (J$,1) 180:CURSOR 6: PRINT J$;J$; 190:FOR K=1 TO 5:A(K)= PEEK (&281D+K): NEXT K: GOTO 20 200:INPUT "Reference chr. :";J$ 210:CLS 220:J$= LEFT$ (J$,1) 230:CURSOR 6: GPRINT A;B;C;D;E; 240:CURSOR 7: PRINT J$;: GOTO 20 使い方は次の通りです。 2,4,6,8:カーソル(点滅している点)を動かします ENTER:カーソルのあるところに点を打ちます C:ほかのキャラクター(ポケコンが持っているもの)をコピーします R:ほかのキャラクター(ポケコンが持っているもの)を参照します E:プログラムを終了します 画面の下の段にでているのが現在制作中のキャラクターを16進数のコード になおしたものです。なお、10進数のほうがよいという人はプログラムの3 0行のHEXを取って下さい。その方が速度も早くなります。また、キーを押 すタイミングが難しいので注意して下さい(BASICではこれが限界でしょ う) 1.4 独単語の表示 今のプログラムを使って、ウムラウトや のコードを作ることができました。 次は、このコードを使って単語を表示させましょう。その際に、どういう文字 列がきたらこのような文字を表示させるか決めておかねばなりません。ここで は、次のように定めます。(かなり速度とメモリーに無駄がありますがこの方 が便利なので・・・) .. .. .. a ”+a” o ”+o” u ”+u” β ”+s” なお、大文字は表示させにくいので省略します。このように決めると、次の ようなプログラムで単語の表示ができるようになります。 10:DIM AA$(0)*80: WAIT 0 20:INPUT AA$(0) 30:FOR I=1 TO LEN AA$(0) 40:A$= MID$ (AA$(0),I,1) 50:IF A$="+" THEN 80 60:PRINT A$; 70:NEXT I: END 80:B$= MID$ (AA$(0),I+1,1) 90:IF B$="a" GPRINT "3845443D40"; 100:IF B$="o" GPRINT "3845444538"; 110:IF B$="u" GPRINT "3C4140217C"; 120:IF B$="s" GPRINT "7E01494936"; 130:I=I+1:GOTO 70 実行させると?が表示されるので、単語を先ほどの約束どうりにいれて下さい。 1.5 電子独和辞典の制作 ここまでできれば後は簡単です。入力された単語がデーターに含まれている かを捜す部分をいれれば終わりです。それでは次のプログラムをいれて下さい。 10:"A" CLEAR : DIM AA$(2)*30:E=4 ←ここにはデーターの数−1をいれて下さい。 20:INPUT "ドイツゴ:";AA$(0) 30:FOR J=0 TO E 40:RESTORE 1000+10*J:READ AA$(1) 50:IF AA$(0)<=AA$(1) THEN 70 60:NEXT J: BEEP 1: PRINT "タンゴ ガ アリマセン": END 70:CLS : WAIT 0: FOR I=0 TO LEN AA$(1) 80:A$= MID$ (AA$(1),I,1) 90:IF A$<>"+" PRINT A$;: GOTO 160 100:B$= MID$(AA$(1),I+1,1) 110:IF B$="a" GPRINT "3845443D40"; 120:IF B$="o" GPRINT "3845444538"; 130:IF B$="u" GPRINT "3C4140217C"; 140:IF B$="s" GPRINT "7E01494936"; 150:I=I+1 160:NEXT I 170:WAIT: CURSOR 24: PRINT AA$(2); 180:GOTO 20 1000:DATA "beginen","ハジメル" 1010:DATA "essen","タベル" 1020:DATA "gehen","イク" 1030:DATA "m+ussen","..シナケレバナラナイ" 1040:DATA "stehen","タツ" 単語のデータは、アスキーコードの若い順にいれて下さい。これを少し改良 すれば和独辞典(こっちの方が例としてはよかったかも知れません)になりま す。皆さんやってみて下さい。 第2章 ポケコンにハッキング!! −パスワードを忘れた場合に備えて−  皆さんは、ハッカー(注)という言葉をご存じでしょう。よそのコンピュータ に侵入して、悪事を働くあのハッカーです。このPC−1470Uでも、他人 が勝手に操作して、プログラムやデータが壊されないように、パスワード機能 が付いています。ここでは、このパスワード機能について調べ。万が一、パス ワードを忘れたときに備えるということと、そして他人のポケコンにハッキン グして、いたずらできるようにします。 注)今ではクラッカー(Cracker)といってハッカー(Hacker)と区別することが 多いです。 2.1 パスワード機能について。  このポケコンのパスワード機能は、おそらく今までで最強のものでしょう。 パスワードの設定は、次のようにPASSコマンドによって行います。   例:PASS”PC−1470”  こうすることによって、”PC−1470”というパスワードがかけられま す。一度パスワードがかけられると、再び、PASS”PC−1470”とし て、パスワードが解除されるまで、LIST、NEW、CSAVEなどのプロ グラム自体を操作する命令がERROR 1になります。さらに、ほかのポケ コンと違って、PEEK、POKE、CALLなどのメモリーを直接操作する 命令もERROR 1となるので、解析がやりにくくなっています。 2.2 パスワードを捜せ!  さて、このパスワードはポケコンのどこに記録されるのでしょうか。このポ ケコンのメモりー配置(電言板2参照)を見てみると、アドレスの&F900〜 &FFFFがシステムエリア(ポケコンが使用する場所)だと書いてあります。 ということは、システムエリアを調べていけば、パスワードの在処が分かるわ けです。次のプログラムを入力してください。 10:WAIT 0 20:FOR I=&FFE0 TO &FFE6 30:PRINT CHR$ PEEK I; 40:NEXT I  入力が終わったら、PASS”PC−1470”としてパスワードをかけて おいて下さい。それでは、実行してみましょう。どうですか、先ほどパスワー ドとして登録した”PC−1470”が表示されるでしょう。実は、&FFE 0から&FFE6までがパスワードを記録する場所として使われているのです。 これを悪用すると次のようなこともできます。 10:POKE &FFE0,246,246,246,246,246,246,246  このプログラムは、パスワードを7つのハートマークにしてしまいます。と ころが、ハートマークというキャラクターは、キーボードから入力できないの で、リセットしない限りパスワードを解除することはできません。  しかし、このパスワードを表示する方法では、せっかくパスワードを記録す る場所がわかっていても、パスワードがかかっていない状態の時しかプログラ ムの入力ができませんし、またパスワードがかけられるとダイレクトモードで はPEEKが使えないので、パスワードを忘れてしまったときや、他人のポケ コンに侵入するときには使えません。(予め、先ほどのプログラムを入れてお けば別ですが。) 2.3 鍵はAER(数式記憶モード)にあり! ところが、なんとパスワードがかかっていても、PEEKを使う方法があっ たのです。それは、PC−1470Uに登載されているAER(数式記憶)に あったのです。電源を入れてから、一度もERRORを出さなければ、AER に記憶されたPEEK文を使うことができたのです。次のように操作してみて 下さい。 PRO MODE PASS "PC-1470" AER MODE 01:PEEK :F(X)= PEEK X 一度電源を切って、再び電源を入れる。 RUN MODE キーを押して、さっきのAERを呼び出す。 "X="と表示されたら&FFE0と入力。 80.(&FFE0の内容)と表示される。  ということは、先ほどのパスワード表示プログラムを入れておけば(そのま までは駄目ですが)、ERRORを起こさない限りパスワードを見ることがで きるのです。AERで次のようにいれて下さい。   例:01:PASS : CHR$ PEEK &FFE0+ CHR$ PEEK &FFE1+ CHR$ PEEK &FFE2+ CHR$ PEEK &FFE3+ CHR$ PEEK &FFE4+ CHR$ PEEK &FFE5+ CHR$ PEEK &FFE6  パスワード表示プログラムのAER版です。一度に入力できませんので途中 まで入力したら、一度ENTERを押してそれから続きを入力して下さい。使 い方は通常のAERと同じです。 2.4 究極のパスワード解除法  ここまでくると、ワンタッチでパスワードが外したくなってきませんか。パ スワードがかかっている他人のポケコンでは先ほどの方法を使うほかはありま せんが、自分のポケコンならば、予め次のプログラムを適当な行番号のところ にいれておけば自由に外すことができます。 65200:"Z" POKE &FFEA,PEEK &FFEA AND &DF:END  DEF+Zでパスワードを解除することができます。また、次のようにすれば、 パスワードの状態を反転させることができます。 65200:"Z" POKE &FFEA,PEEK &FFEA XOR &20:END  つまり&FFEAのビット5(&20)が、パスワードがかかっているかい ないかを記録する場所になっていたのです。ところが、PEEKと違いPOK EはAERでは使うことができないので、先ほどのように他人のポケコンでこ の方法を使うことができないのです。 第3章 マシン語の世界 ポケコンに何かさせるときに、普段ならBASICという言語を使ってプロ グラムすればよいわけですが、例えばすごく時間がかかる計算をしたいとか、 BASICではできないことをしたいときはマシン語(機械語とも言う)を使っ てプログラムするしかありません。ここでは、マシン語でのプログラムについ てみていきます。 3.1 マシン語について。 マシン語とは、コンピュータの頭脳に当たるCPU(中央演算装置)が直接 理解することのできる言葉のことであり。普段使っているBASICもマシン 語のプログラムの1つなのです。ただ、BASICはどのコンピュータのもの でも似たような構成になっていますが、マシン語はコンピュータの種類によっ て違っています。PC−1470UではSC61860という8ビット(一度 に0から255までの数値を扱うことができる)のCPUを使っていますから、 SC61860のマシン語を使う必要があります。ここでは、マシン語自体の 説明は省き(詳しく知りたい人は参考文献を参照)、実際にマシン語によるプ ログラムを行うことにします。ただ、PC−1470U内部の解析をする時間 がありませんでしたので、簡単なサンプルプログラムしか作ることができませ んでした。 3.2 キー入力 ゲームなどのプログラムを作るとき、BASICではINKEY$を使って キー入力をします。まず、これをマシン語で行うには次のようにします。 コード ニモニック(以下同様) FF 44 CAL 1F44 または 78 1F 44 CALL 1F44 &1F44はROM内のキー入力サブルーチンのエントリーアドレスになっ ています。普通、サブルーチンコールはCALL命令(コード&78)を使い ますが、&0000〜&1FFFまでのメモリー(内部ROM)へのサブルー チンコールはCAL命令も使うことができ、そのコードは(&E0+サブルー チンの上位アドレス,下位アドレス)と言うように2バイトになります。さて、 結果はAレジスタに次のようなコードで帰ってきます。  キーコード表(ROM内サブルーチン) +---+-----+-----+-----+-----+-----+-----+     |  | 00| 10| 20| 30| 40| 50| +---+-----+-----+-----+-----+-----+-----+ | 0| N | ← | ÷ | − | tan | x2 |     | 1| H | ( | 9 | 3 | cos | √ | | 2| Y | ENT | 8 | 2 | sin | yx | | 3| ↓ | L | 7 | 1 | hyp | EXP | | 4| FSE | O | SML | X | V | BRK | | 5| *1 | → | DEF | S | F | ----| | 6| C・CE| BAS | SHFT| W | R | ----| | 7| M | , | BS | = | ",゚ | ----| | 8| J | P | × | + | log | ----| | 9| U | AER | 6 | . | ln | ----| | A| ↑ | ----| 5 | +/- | DEG| ----| | B| 1/x | ----| 4 | 0 | HEX| ----| | C| ) | ----| Z | C | B | ----| | D| SPC | ----| A | D | G | ----| | E| K | ----| Q | E | T | ----| | F| I | DEL | INS | カナ| ー | ----| +---+-----+-----+-----+-----+-----+-----+ *1 は上下矢印(AER 呼びだしキー) それでは実際にやってみましょう、リストは次の通りです。なお、このプロ グラムをはじめ、ここにあげたプログラムの大部分は、マシン語領域としてA ER(数式記憶)エリアを使用しますので、AERの内容はすべて失われます。 また、AERキーを押すと"RESERVE AREA CLEAR OK.(Y/N)"とでますが、ここ では必ずNを押して下さい。 10:CLEAR : POKE &FF40,&FF,&44,&10,&FF,&50,&52,&37 20:"A" WAIT 0 30:CALL &FF40: PRINT HEX PEEK &FF50: GOTO 30 10行のPOKE文はマシン語を書き込むためのものです。このマシン語の 部分は、&1F44をコールして帰ってきた値を&FF50にかきこむもので す。RUNしたら何か適当なキーを押して下さい、さっきの表にあげた数字が かえってくるでしょう。 3.3 同時キー入力。 3.2にあげた方法で、キー入力をすることができました。しかし、ゲーム などでは、同時に2つ以上のキーが押されているかを知りたい場合がよくあり ます。また、上の方法だとキーを読み込むのに時間がかかるので、特にスピー ドが要求されるとき(次にあげるオルガンの例のようなとき)には余り使いた くありません。そんなときには、ROM内サブルーチンを使わずに、直接キー を読み込む方法が使われます。回路図を見ていただければ分かると思いますが、 全てのキーはCPUのIAポート(内部RAMアドレス&5C)につながって います。だからIAポートを読み出すINA命令(コード&4C)を使えばよ いことが分かります。しかし、IAには8つの信号線しかありませんので、た くさんあるキーの中から読み出したいキーの列を一つ選択してから読み出す必 要があります。PC−1470Uのキーボードはこのキーの列を選択する方法 の違いによって、2つのグループに分けられています。  キーコード表(IAポートによる選択) +-------+-----+-----+-----+-----+-----+-----+-----+-----+ | | 01| 02| 04| 08| 10| 20| 40| 80| +-------+-----+-----+-----+-----+-----+-----+-----+-----+ | IA1:01| ----| C・CE| *1 | FSE | ↓ | Y | H | N | | IA2:02| C・CE| ----| ) | 1/x | ↑ | U | J | M | | IA3:04| *1 | ) | ----| ( | ← | I | K | SPC | | IA4:08| FSE | 1/x | ( | ----| → | O | L | ENT | | IA5:10| ↓ | ↑ | ← | → | ----| P | , | BAS | | IA6:20| Y | U | I | O | P | ----| ----| AER | | IA7:40| H | J | K | L | , | ----| ----| ----| | IA8:80| N | M | SPC | ENT | BAS | AER | ----| ----| +-------+-----+-----+-----+-----+-----+-----+-----+-----+ *1 は上下矢印(AER 呼びだしキー)  この表にあるキーは、回路図で横の線でIA1〜IA8と書かれたところに あるキーです。この表にあるキーを読み出すには次のように行います。 10 3E 00 LIDP 3E00 02 00 LIA 00 52 STD 12 5C LIP 5C 02 ?? LIA ?? ←読み出したいキーのスキャンライン DB EXAM    (表の左側の数字)を入れる 5D OUTA 4C INA このマシン語は、まず&3E00に0を書き込み、IAにスキャンラインを 出力して、次にIAポートを読み込むものです。つまり、さきにIAポートに 読み出したいキーの列を出力しておいてから、IAポートを読み出すと押され たキーに対応するビットが1になります。なお、このとき&3E00は必ず0 である必要があります。さもないと、次にあげる&3E00によるキーの列の 選択と間違えられてしまいます。それでは、具体的にIA6のライン(&20) で実験してみましょう。 10:CLEAR : POKE &FF40,&10,&3E,&00,&02,&00,&52,&12,&5C,&02,&20,&DB,&5D,&4C, &10,&FF,&60 15:POKE &FF50,&52,&37 20:"A" WAIT 0 30:CALL &FF40:PRINT HEX PEEK &FF60: GOTO 30 RUNさせてから、Y、U、I、O、Pのうちのどれかのキーを押して下さ い。例えば、YとIを押すと、5が表示されるのが分かるでしょう。 先ほどの表にないキーは、回路図で横の線でKS1からKS7と書かれたと ころにつながっているものです。このキーは、メモリーに割り付けられたIO コントローラ(ゲートアレイ:LZ92K3B)で制御されます。次の表を見て下さ い。  キーコード表(&3E00による選択) +---+-----+-----+-----+-----+-----+-----+-----+-----+ | | 01| 02| 04| 08| 10| 20| 40| 80| +---+-----+-----+-----+-----+-----+-----+-----+-----+ | 1| 7 | 8 | 9 | ÷ | DEL | ----| ----| ----| | 2| 4 | 5 | 6 | × | BS | SHFT| DEF | SML | | 3| 1 | 2 | 3 | − | INS | Q | A | Z | | 4| 0 | +/- | . | + | = | W | S | X | | 5| hyp | sin | cos | tan | カナ| E | D | C | | 6| HEX | DEG | ln | log | ゙、゚ | R | F | V | | 7| EXP | yx | √ | x2 | ー | T | G | B | +---+-----+-----+-----+-----+-----+-----+-----+-----+ この表にあるキーを読み出すには次のようにします。 12 5C LIP 5C 60 00 ANIM 00 5D OUTA 10 3E 00 LIDP 3E00 02 ?? LIA ?? ←読み出したいキーのスキャンライン 52 STD  (表の左側の数字)を入れる 4C INA つまり、キーを読み出すのにIAポートだけでは不足なために&3E00で キーの列を指定するわけです。&3E00は、IOコントローラのキー制御の アドレスになっています。また、このときIAポートには0が出力されていな ければなりません。この場合でも先ほどと同様に押されたキーのビットが1に なります。次のプログラムで実験してみて下さい。 10:CLEAR : POKE &FF40,&12,&5C,&60,&00,&5D,&10,&3E,&00,&02,&02,&4C,&10,&FF, &60,&52,&37 20:"A" WAIT 0 30:CALL &FF40: PRINT HEX PEEK &FF60: GOTO 30 このプログラムは2段目のキーを読みだします。RUNしてから、SHIFT、 DEF、SMLのキーを同時に押してみて下さい。おそらくE0と表示されるでしょ う。 3.4 音だし BASICで音を出す命令にはBEEPがあります。マシン語でBEEP文 と同じように音を出してみます。PC−1470UのブザーはCONTROL ポートにつながっています。CONTROLポートのビット4(&10)を1 にするとブザーON、0にするとブザーOFFになります。次のプログラムを 実行してみて下さい。 10:CLEAR 20:POKE &FF40,&02,&00,&80,&DB,&12,&5F,&61,&10,&DF,&10,&00,&00,&1F,&60,&01,&DF 30:POKE &FF50,&4D,&4D,&40,&2B,&10,&37 40:"A" CALL &FF40: GOTO 40  マシン語部ソースリスト 02 00 LIA 00 80 LP 00 DB EXAM ;Iレジスタのクリア 12 5F LOOP:LIP 5F 61 10 ORIM 10 DF OUTC ;ブザーON 10 00 00 LIDP 0000 1F FILD ;時間稼ぎ(Iレジスタ分の時間) 60 01 ANIM 01 DF OUTC ;ブザーOFF 4D NOPW 4D NOPW 40 INCI 2B 10 JRNCM LOOP ;Iレジスターが&FFになるまで繰り返し 37 RTN ;BASICに戻る どうですか、ゲームの効果音のような音がでたでしょう。ここではIレジス タで音程を決定しています。これを応用すると次のようなオルガンプログラム になります。なお、このプログラムは同時キー入力の方法が分かる前に作った ものなのでROM内サブルーチン(&1F44)を使っています。そのため音 が多少変なふうに聞こえます。 100:"A" RESTORE 110:FOR I=&FF40 TO &FFC7 120:READ A: POKE I,A 130:NEXT I: END 140:DATA &FE,&9C,&67,&4F,&2A,&28,&01,&01,&84,&10,&FF,&76,&1A,&84,&03,&00 150:DATA &14,&24,&67,&FF,&38,&18,&80,&DB,&02,&40,&12,&5F,&61,&10,&DF,&10 160:DATA &20,&00,&1F,&60,&01,&DF,&CE,&CE,&43,&29,&10,&2D,&2C,&6B,&08,&39 170:DATA &30,&37,&37,&37,&37,&37,&77,&FF 180:DATA 255,76,72,255,255,255,255,255,66,63,255,255,255,255,57,53 190:DATA 255,255,255,49,255,255,255,46,43,255,255,255,255,255,255,255 200:DATA 255,255,255,255,255,255,255,19,24,28,255,36,166,128,124,21 210:DATA 26,31,33,39,147,115,255,16,18,255,255,255,159,108,102,255 220:DATA 255,255,255,255,140,93,90,255,255,255,255,255,255,82,255,255 230:"B" CALL &FF40: END ソースリスト(打ち込む必要はありません) FF40:FE 9C RES: CAL 1E9CH ;キー入力 FF42:67 4F CPIA 4FH FF44:2A 28 JRNCP NOKEY ;キーが無かったらBREAKチェックへ FF46:01 01 LIJ 01H FF48:84 LP 04H FF49:10 FF 76 LIDP 0FF76H ;キーデータアドレス−1をXレジスタに転送 FF4C:1A MVBD FF4D:84 LP 04H FF4E:03 00 LIB 00H FF50:14 ADB ;キーデータアドレスを計算 FF51:24 IXL ;キーデータを読む FF52:67 FF CPIA 0FFH FF54:38 18 JRZP NOKEY ;キーデータが無かったらブレイクチェックへ FF56:80 LP 00H FF57:DB EXAM ;キーデータをIレジスタに転送 FF58:02 40 LIA 40H ;リピート回数 FF5A:12 5F LOOP1: LIP 5FH FF5C:61 10 ORIM 10H FF5E:DF OUTC ;ブザーオン FF5F:10 20 00 LIDP 2000H FF62:1F FILD ;時間稼ぎ FF63:60 01 ANIM 01H FF65:DF OUTC ;ブザーオフ FF66:CE NOPT FF67:CE NOPT FF68:43 DECA FF69:29 10 JRNZM LOOP1 ;リピート回数まわったら次へ FF6B:2D 24 JRM RES FF6D:6B 08 NOKEY: TEST 08H FF6F:39 30 JRZM RES ;ブレイクが押されていたら終わり FF71:37 RTN DEF+Aでマシン語を書き込み、DEF+Bで実行します。AからINSまでのキーを 鍵盤に見立てて演奏します。一応Dがドになっていますが音程の調節をしてい ませんので音程はでたらめです。 3.5 ROMの探検 マシン語でプログラムをするときに、すべて自分でプログラムを作るのは大 変です。普通はROMの中にあるサブルーチンを呼び出して使います。ところ が、PC−1470Uは生協でしか売っていないために、雑誌などを見ても解 析記事が全く載っていません。そのために本格的にマシン語でプログラムをし ようと思ったら自分で解析をする必要があります。それには、ROMのデータ を読みだして、逆アセンブルすればよいわけです。逆アセンブルは、コード表 さえあれば手でできるので、ここではROMの読み出し方についてしらべます。 PC−1470UのROMには2種類あります。まず1つめはCPUに内蔵 のROMで、そのアドレスは&0000〜&1FFFまで8Kバイト分です。 普通メモリーを読み出すにはBASICのPEEK文を使えばよいわけですが、 この内蔵ROMにはPEEK文を使うことができません。このROMを読み出 すにはマシン語の特殊な命令を使う必要があります。2つめは外部ROMとい われる部分でアドレスは&4000〜&7FFFに割り当てられています。し かしマニュアルを見ても分かるとおりPC−1470UのROMは全部で13 6Kバイト、外部ROMだけでも128Kバイトもあります。そのために12 8Kバイトを16Kバイト毎に分けそれぞれをバンク0〜7と呼びます。そし てそのバンクのうちの1つを実際のメモリー空間に割り当てます。このような 方法をバンク切り替えと呼びます。バンク切り替えは、IOコントローラの役 割になっています。具体的には、&3400にパンク番号を書き込みます。ま た現在のバンクを調べるには&4000を読みだします。但し、絶対にBAS ICのPOKE文で&3400に書き込むようなことはしないで下さい。確実 に暴走します。 次にバンクROM、内部ROM対応のメモリーダンププログラムを示します。 本当は、オールマシン語モニターを発表したかったのですが、時間が無いので BASICと混合になりました。(電言板2:P.63のメモリーダンプの移 植です。)また、32Kバイト以上のRAMカードをつけるとRAMでもバン ク切り替えを行いますが、RAMのバンク切り替えにはたぶん対応していませ ん。またこのプログラムは、メインRAMを使いますので、このプログラム以 外のプログラムを同時にいれたり、大きな配列変数を使ったりすると暴走する ことがあります。 10:CLEAR : GOSUB 170: POKE &F090,ASC ":":DIM X$(0)*24 20:"D" WAIT 30: PRINT "MEMORY DUMP": WAIT 30:INPUT "BANK NO.";B 40:POKE &F004,B 50:INPUT "START ADDRESS = ";S 60:IF S>&FFF8 THEN 50 70:INPUT "END ADDRESS = ";E 80:IF EB THEN C=B:B=A:A=C ELSE GOSUB *NEXT  いまこんなテキストがあったとします。ここでELSE以下が不用になった ので消したいと思います。こんなときに、まさかBSやDELキーを使ったり、 スペースでELSE以下を一文字づつ消しているのではないでしょうか。こん なときは、カーソルをELSEの所に持っていき、CTRL+Eを押せば良い のです。このように、コントロールキーを使うことによって、プログラムの修 正ははるかに楽になるのです。別にこれは隠しコマンドではありませんがので、 マニュアルにもちゃんとかいてあります。(PC−E500取扱説明書183 ページ及び、BASICリファレンスマニュアルのINPUT$のところ) 2.12 なんだこれは(RESERVED)  これはPC−E500シリーズの隠しコマンドの中でも意味不明のコマンド です。どうやらこれは、ほかの機種のプログラムをCLOAD @で読み込ん だときに、PC−E500シリーズにない命令があったところに出てくるよう です。このRESERVED命令は次のように使います。 RESERVED &H??  ←??はBASIC中間コードの2バイト目  必ず&Hを使った16進数で表すこと。  PC−E500シリーズのBASIC中間コードは次のようになっています。 (PC−1480Uの人は電言板3に中間コード表が出ています。ただしバグ 入りですけど。) +---+---------+---------+---------+---------+---------+---------+ | |  00 |  10 |  20 |  30 |  40 |  50 | +---+---------+---------+---------+---------+---------+---------+ | 0| | RUN | CSAVE | DIM | LTEXT | CLS | | 1| | NEW | OPEN | CALL | GRAPH | LOCATE | | 2| | CONT | CLOSE | POKE | LF | TO | | 3| | PASS | SAVE | GPRINT | CSIZE | STEP | | 4| | LIST | CONSOLE | PSET | COLOR | THEN | | 5| | LLIST | *1 | PRESET | | ON | | 6| | CLOAD | DEGREE | BASIC | DEFDBL | IF | | 7| | MERGE | RADIAN | TEXT | DEFSNG | FOR | | 8| | LOAD | GRAD | | | LET | | 9| | RENUM | BEEP | | | REM | | A| | AUTO | WAIT | ERASE | | END | | B| BTEXT$ | DELETE | GOTO | LFILES | | NEXT | | C| BDATA$ | FILES | TRON | KILL | | STOP | | D| MEM$ | INIT | TROFF | COPY | | READ | | E| | | CLEAR | NAME | | DATA | | F| | | USING | SET | | PAUSE | +---+---------+---------+---------+---------+---------+---------+ +---+---------+---------+---------+---------+---------+---------+ | |  60 |  70 |  80 |  90 |  A0 |  B0 | +---+---------+---------+---------+---------+---------+---------+ | 0| PRINT | PAINT | MDF | FACT | RND | EOF | | 1| INPUT | OUTPUT | REC | LN | AND | DSKF | | 2| GOSUB | APPEND | POL | LOG | OR | LOF | | 3| | AS | ROT | EXP | NOT | LOC | | 4| LPRINT | ARUN | DECI | SQR | PEEK | | | 5| RETURN | AUTOGOTO| HEX | SIN | XOR | | | 6| RESTORE | ELSE | TEN | COS | | NCR | | 7| CHAIN | RESUME | RCP | TAN | EVAL | NPR | | 8| GCURSOR | ERROR | SQU | INT | | | | 9| LINE | KEY | CUR | ABS | | | | A| LLINE | | HSN | SGN | | | | B| RLINE | | HCS | DEG | | | | C| GLCURSOR| | HTN | DMS | | | | D| SORGN | | AHS | ASN | POINT | | | E| CROTATE | | AHC | ACS | PI | | | F| CIRCLE | | AHT | ATN | FRE | | +---+---------+---------+---------+---------+---------+---------+ +---+---------+---------+---------+---------+ | |  C0 |  D0 |  E0 |  F0 | +---+---------+---------+---------+---------+ | 0| ERN | ASC | | CHR$ | | 1| ERL | VAL | | STR$ | | 2| | LEN | | HEX$ | | 3| | | | | | 4| | | | | | 5| | | | | | 6| | | | | | 7| | | | | | 8| | | OPEN$ | | | 9| | | INKEY$ | | | A| | | MID$ | | | B| | | LEFT$ | | | C| | | RIGHT$ | | | D| | | | | | E| | | | | | F| | | | | +---+---------+---------+---------+---------+ 注意 これらのコードはすべて2バイト目であり、1バイト目はすべて&HFEとなっている *1は RANDOMIZE 命令 コード&HE8のOPEN$は実際には使われていない。OPEN$はOPE Nと$に分けて扱われている RESERVEDにコードは割り当てられていない。 EX版注) 構造化BASIC 搭載機ではここで空欄になっているところに WHILE などが登録 されているはずです。  このRESERVED命令は、奇妙なことにリターンキーを押した時点で、 普通の命令に置き換えられてしまいます。まあ、こんな命令使っても全くメリッ トはないでしょう。 2.13 ERROR命令  ERROR命令は、普通はON ERROR文として使いますが、単独でエ ラーを発生する命令としても使えます。 ERROR エラーコード  とするとエラーコードに相当するエラーを発生します。ところで、エラーコー ドにもマニュアルに書いていないものがあります。次のように操作してみて下 さい。 ERROR 0  Breakとでましたね。実は、エラーコード0はユーザーブレークのコー ドになっていたのです。そのほかにも次のようなものがあります。 1:(良くわからない。実行すると、必ずRUNモードになる) 99:Low battery  電池が切れる直前に発生する。普通は、これを表示した直後に電源が自動的 に切られる。 2.14 インジケータを操ろう  PC−E500シリーズの画面の上の方には、RUNだとかCAPSとか書 いてある部分があります。これは、表示シンボルまたはインジケータと呼ばれ るものです。さて、このインジケータをBASICから操ることができないも のでしょうか。一般的なポケコン・マイコンでは画面は表示専用のメモリー、 V−RAMに書き込まれています。よって、V−RAMを直接操作することに よって図形を書いたり、文字を書いたりすることができるようになっています。 さて、PC−E500シリーズの場合はどうなっているのでしょうか。  結論からいうと、PC−E500シリーズのV−RAMは、BASICから 直接操作することができないのです。そのために画面を操作するには、GPR INTとか、LINEとかいった命令を使うしかないのです。  それでもインジケータの内容を操作することはできます。ワークエリア内に、 インジケータの状態を格納している場所があります。それは次の通りです。 +-------+-------+-------+-------+-------+-------+ | | 01 | 02 | 04 | 08 | 10 | +-------+-------+-------+-------+-------+-------+ | BFC97H| BATT | | | | | | BFC98H| BUSY | RUN | PRO | DBL | | | BFC99H| 小文字| カナ | HYP | CAPS | 2ndF | | BFC9AH| PRINT | E | RAD | G | DE | +-------+-------+-------+-------+-------+-------+  左側にあるのがアドレスです。つまり、BATTをつけたいならば、&HB FC97に1を書き込めば良いのです。ただし、この方法には1つだけ欠点が あります。それは、書き込んだ後に画面クリアをしなければインジケータが変 化しないということです。これは、直接画面を操作しているのはないので仕方 がありません。 2.15 いたずらを防止しよう どこの世界にも人の計算機を勝手に触ってプログラムなどを消されてしまっ たりすることがあります。このようなときにポケコンを守るにはどうすれば良 いのでしょう。一番確実なのは、パスワードを掛けることですがこれもいつ破 られるかわかりません。(しかし、パスワードを掛けるとプログラム中でもP EEK文が使えないというのはどういうこった?)しかも、これでは全く芸が ありません。そこで、別の方法を考えてみましょう。  ワークエリア内にオートパワーオフ時間を設定しているところがあります。 ここをいじくってみましょう。そのアドレスは&HBFCBC−&HBFCB Dになっています。それでは、ここを操作する前にすぐに元に戻せるようにし ておきましょう。(自分も使えなくなったらしょうがないですから) KEY 5,"POKE &HBFCBC,176,4"+CHR$ 13  これでファンクションキーの5番を押せば元に戻るようにしました。ちなみ に、デフォルトのオートパワーオフ時間は、約11分間になっています。それ では、これを約1秒に設定してみます。 POKE &HBFCBC,1,0  あっという間に電源が切れました。 2.16 反転文字  さて、皆さんはポケコンのメニュー画面をみて「あれ、このMAIN ME NUのところの反転文字はどの様にして表示しているのだろう」と思ったこと はありませんか。じつは、ワークエリアの一つに反転文字を表示するかどうか を示すところがあるのです。次のように操作してみて下さい。 POKE &HBFCA1,64  表示される文字が、すべて反転文字になったでしょう。元に戻すには、次の ようにします。 POKE &HBFCA1,0 2.17 どうにも止まらない  実行時間の長いプログラムを実行していて絶対に誰にもブレークされたくな いとか、ゲームのプログラムだけれどゲーム中に変数の値を書き換えてインチ キをする人がいるなどというときに、ブレークキーを押してもプログラムが中 断しないようにできたら便利ですね。このようなときには次のような一文をプ ログラムに付け加えて下さい。 POKE &HEA,0  これでブレークキーは効かないようになります。ただし、これを実行したあ とでプログラムが永久ループにはいってしまったというときには困るので、必 要のないときには次のように操作しておいて下さい。 POKE &HEA,8 第3章 PC−E500シリーズマシン語講座  PC−E500シリーズでは新設計の8ビットCPUが登載されています。 このCPUは16ビット機並の1MBまでのメモリを扱うことのできるすごい ものです。この章ではPC−E500シリーズでマシン語を扱うにはどうすれ ば良いのかを述べていこうと思います。 3.1 マシン語とは何か  皆さんが普段ポケコンを使っているときにはBASICと呼ばれるコンピュー タ言語を使ってプログラムを作ったりしているはずです。このBASICは高 級言語と呼ばれるものの一つです。コンピュータ言語の高級低級というのは、 プログラムのつくりやすさとか見やすさとかいったものとは全く関係がありま せん。(そんなこといったらBASICなんか超低級言語になってしまう!) 高級言語というのはプログラムを作るときにポケコンの内部構造を知っている 必要がないということです。たとえば、画面に「A」という文字を書きたいと しましょう。このとき高級でない言語を使った場合(マシン語など)ではメモ リーの配置とか画面制御LSIの構造などを知っている必要があります。しか し、BASICならばPRINT ”A”とするだけですんでしまいます。こ のように便利なBASICではありますが、プログラミングの腕が上達してく るにつれてどんどん不満が出てくるものです。  その一つはBASICは実行速度が遅いということです。BASICはイン タプリタ方式を採用しています。BASICは直接CPUが理解できるもので はないので、何等かの方法でCPUに理解させなければなりません。インタプ リタ方式とはプログラム言語で書かれたプロクラムの各命令をインタプリタと いうプログラム(このポケコンの場合はBASICという名前のプログラム) が間接的に解釈してCPUに伝えるものです。そのため実際にその命令の内容 が実行されるよりも、命令の解釈のためにかなりの時間がかかってしまいます。 なお、インタプリタ方式のほかに、プログラム言語で書かれたプログラムを直 接CPUが理解できるように翻訳してしまうコンパイル方式というのもありま す。コンパイル方式であれば、インタプリタ方式のような無駄はありません。 しかし、コンパイルをするプログラム(コンパイラと呼ぶ)を作るのが大変な のと、メモリーの関係でポケコン用のコンパイラというのは余り見かけません。  BASICに対する不満のもう一つは細かい処理ができないことです。例え ば一瞬にして画面を反転したり、一度にたくさんのキーの状態を調べたりとい うのはBASICではとてもできません。  そこでマシン語が登場するわけです。マシン語でプログラムを作るメリット として、CPUが直接理解できるのでスピードが速いこと、ハードウェアに近 い処理ができることなどがあります。しかし、マシン語はBASICと違って プログラムを作るのが非常に面倒で難しいのでしっかりとした、プログラムロ ジックを考えておかないとひどい目にあいます。変なプログラムを実行させる とポケコンが言うことを聞かなくなったりすることがあります。(暴走という) 3.2 PC−E500シリーズのCPU  マシン語を使うためには、まずCPUの構造を知っておく必要があります。 マシン語というのは各CPUによって異なっています。PC−E500シリー ズに使われているCPUはSC62015というもので、ポケコン専用に開発 されたものです。そのために、マイコンなどに使われている汎用のCPUと比 べると変わった機能を持っています。このCPUは次のような構造をしていま す。 a)アキュムレータ及びレジスタ  CPUには数を記憶する場所があります。これをレジスタと呼んでいます。 CPUが計算できるのはレジスタ内の数、またはレジスタで指定されたメモリー にある数だけです。その中でも、本当の計算を行う回路につながっているもの をアキュムレータと呼びます。PC−E500シリーズのCPUであるSC6 2015には次のようなレジスタがあります。なおビット(Bit)というの はコンピュータの扱う情報の最小単位であり1ビットはスイッチのon/of fを表すのと同じ情報量です。また8ビットをバイト、16ビットをワードと 呼んでいます。 +-------------------+-------------------+ | B 8BIT| A 8BIT| +-------------------+-------------------+ | IH 8BIT| IL 8BIT| +---------------+-------------------+-------------------+ | X 20BIT| +-------------------------------------------------------+ | Y 20BIT| +-------------------------------------------------------+ | U 20BIT| +-------------------------------------------------------+ | S 20BIT| +---------------+---------------------------------------+ | PS 4BIT| PC 16BIT| +---------------+---------------------------------------+ Aレジスタ  アキュムレータです。従って、ほとんどの計算はこのAレジスタを使うこと になります。またBレジスタと併せて16ビットのBAレジスタとしても使う ことができます。なお、一般にCPUが何ビットであるかを示すのはアキュム レータが何ビットの幅を持っているかということ、実際にCPUから出ている データ用の信号線(データバス)の数で表しています。このAレジスタは8ビッ トですので、SC62015は8ビットCPUであるというわけです。 Bレジスタ  Aレジスタの補助レジスタです。Bレジスタ単独で使うことはできません。 IH、ILレジスタ  リピート命令(後の命令の解説を参照)に対してリピートの回数を指定する レジスタです。通常IHとILはペアで16ビットのIレジスタとして使われ ます。 X、Yレジスタ  外部のメモリーをアクセスするときに、そのアドレスをしまうために使われ ます。なお、このようにほかのメモリーを指し示すものをポインタと呼んでい ます。 U、Sレジスタ  この2つのレジスタは、スタックポインタと呼ばれます。スタックとは、命 令を実行する際の途中経過などを一時的にしまっておくための場所のことで、 そのスタックの存在する場所を示すのがこのスタックポインタというものです。 Uレジスタはユーザースタックポインタと呼ばれ、ユーザーが自由に使うこと ができ、またCPUが勝手に使うこともありません。それに対しSレジスタの 方はシステムスタックポインタと呼ばれ、CPUがサブルーチン呼び出しをす るときなどに現在実行中の命令の場所を記録するために使われます。そのため に、Sレジスタを操作するには十分注意が必要です。 PC、PSレジスタ  PCレジスタは、PSレジスタと共に現在実行中の命令の場所を示していま す。SC62015ではPCレジスタとPSレジスタが併せて20ビットのた めに2の20乗つまり1Mバイトまでのプログラムを実行できるわけです。な お、PSレジスタの方は、特別な命令を使わない限り変更されません。  このほかに、CPUの動作状態を示すフラグというものが入っているレジス タFがあります。フラグには次の様なものがあります。 Cフラグ  キャリーフラグともいいます。計算結果が、オーバーフローもしくはアンダー フローしたときにセットされます。 Zフラグ  ゼロフラグともいいます。計算結果が0になったときにセットされます。  このFレジスタは直接操作することができません。 b)内部RAM  このCPUには、外部のメモリーのほかにCPUの内部に256バイトのメ モリーを持っています。この内部RAMのうちはじめの236バイト(00H からEBH)までは、普通のRAMのように扱えます。しかし、残りの20バ イトには内蔵I/Oなどの制御用のメモリーが割り当てられていますので、内 部RAMを使うときには十分注意しなければなりません。 アドレス ECH BP RAM BASE POINTER EDH PX RAM PX POINTER EEH PY RAM PY POINTER  この3つは、内部RAMをアクセスする場合のポインタとして使われます。 この中でもBPは、何も指定しなかったときに(後の内部RAMのアクセスを 参照)必ず使われるという特別な意味を持っています。 EFH AMC ADRESS MODIFY CONTROL  これは何をするのかよくわかりませんが、おそらく内部RAMのアクセスに おいてECHからの特別なRAMを保護するために使われるものと思われます。 F0H KOL KEY OUTPUT BUFFER(LO) F1H KOH KEY OUTPUT BUFFER(HI) F2H KI KEY INPUT BUFFER  この3つは、キーボードの制御に使われます。KOLとKOHでキーボード マトリックスの行を指定すれば、KIにその行にあるキーの状態が返ってきま す。ただし、キーポートはシリアルインタフェースのコントロールにも使われ ているので注意して下さい。 F3H EOL E-PORT OUTPUT BUFFER(LO) F4H EOH E-PORT OUTPUT BUFFER(HI) F5H EIL E-PORT INPUT BUFFER(LO) F6H EIH E-PORT INPUT BUFFER(HI)  この4つは、汎用I/Oポートのコントロールに使われます。汎用I/Oポー トはプリンタ・ポケットディスク・カセット(リモート)・シリアルポートの 制御に使われています。 F7H UCR UART CONTROL REGISTER F8H USR UART STATUS REGISTER F9H RXD UART RECIEVE BUFFER FAH TXD UART TRANSMIT BUFFER  この4つはシリアルポートの一番重要な部分である、パラレル←→シリアル 変換に使われます。UCRはボーレートなどの設定に、RXD、TXDは実際 のデータのやり取りの際に使われます。 FBH IMR INTERRUPT MASK REGISTER FCH ISR INTERRUPT STATUS REGISTER  この2つは、割り込み制御用です。IMRの方は割り込みを禁止したり、許 可したりするときに使われます。 FDH SCR SYSTEM CONTROL REGISTER FEH LCC LCD CONTRAST CONTROL FFH SSR SYSTEM STATUS REGISTER  この3つはそのほかのI/Oをコントロールするときに使われます。SCR はブザーやカセット出力のコントロールに使われます。SSRはONキーの状 態を調べるときなどに使います。 c)その他  PC−E500シリーズのCPUであるSC62015は1Mバイトのメモ リーをアクセスできると前に書きましたが、実際にPC−E500シリーズで 1Mバイトものメモリーが使えるわけではありません。そこで1Mバイトのメ モリー空間のどこにメモリーが割り当てられているのかを示してみました。 00000H+---------------------+ |   内部RAM | 00100H+---------------------+ |    空き | 40000H+---------------------+ | RAMカード領域 | | 7FFFFHから前に向かっ| | て確保される | 80000H+---------------------+ | 本体内RAM領域 | | 実際にはB8000Hから | | BFFFFHまで | C0000H+---------------------+ | エンジニアソフトウェ| | アROM | | PC−E500のみ | E0000H+---------------------+ | BASIC ROM | | | | | FFFFFH+---------------------+  RAMカード領域は256Kバイト分ありますが、実際に売られているRA Mカードは最大でも64Kバイトしかありません。そのために実際にRAMが 装着されているところ以外では、ほかのメモリーの影が現れてしまいます。こ れは256Kバイト分の領域がありながら32KBのメモリーしか装着されて いない本体内のRAMにもあらわれます。(80000HとB8000Hは同 じメモリーを選択してしまう)これは将来PC−E500シリーズの後継機が 出たときへの準備でしょう。(どこかでフラットパッケージの1MSRAM、 例えば日立のHM628128-LFP12なんてのが手にはいれば、メモリーを128KB に拡張するのですが。) 3.3 マシン語を使う前に  PC−E500シリーズでは、ほかの機種と違って全てのメモリーがファイ ルによって管理されています。そのために、勝手なメモリーにマシン語のプロ グラムを書き込むと、マシン語のプログラムが暴走するどころか、BASIC のファイル管理システムが破壊され、オールリセットするしかなくなることも あります。そのために、あらかじめ必要なメモリーをBASICの管理から外 す必要があります。そのためには次の様にします(マニュアルのPOKE文の 説明を参照) POKE &HBFE03,&H1A,&HFD,&H0B,&H??,&H??,&H?? ← 確保するバイト数 CALL &HFFFD8  こうすることによって、0BFBFFHから前に向かってメモリーがマシン 語領域として確保されます。 3.4 マシン語命令セット  それでは、SC62015の命令を一つづつみていくこととしましょう。な お、一般にマシン語はマシン語そのものではなくて、ニモニックというもので 表します。というのもマシン語は単なる数字の羅列に過ぎませんから、これを 理解するのはまず無理だからです。そのために、マシン語と意味のある言葉と を対応させて、普段は人間の理解できる言葉の方を使いますこれをニモニック と呼びます。ここでもマシン語の命令をニモニックでみていきますが、実際に 実行させるためには本来のマシン語に戻してやらなければなりません。この作 業をアセンブルといいます。その際に注意することがあります。 1:OPコードは2進数、オペランドは16進で表しています。 例 0000 1r1- n :MV r1,n (8ビット)  オペコードは00001r1−で1バイト、オペランドはnで1バイトです。 なお、一般に数値が2進数であることを表すためにB、16進数であることを 表すためにHをもちいます。 例 1001 10進数 1001B  2進数(10進数では9) 1001H 16進数(10進数では4097) 2:r1-やr1'はレジスタを示し、これらは2進数で次の様になっています。 +---------+-----+-------+ | | A | 000| | r1 | IL| 001| +---------+-----+-------+ | | BA| 010| | r2 | I | 011| +---+-----+-----+-------+ | | | X | 100| | | r4| Y | 101| | | | U | 110| | +-----+-----+-------+ | r3 | S | 111| +---------+-----+-------+ 例 0000 1r1- n :MV r1,n (8ビット)  このときに、MV A,02Hという命令を考えると、r1−に当たるのは Aレジスタの場合000ですから、オペコードは00001000Bつまり0 8Hとなります。また、nは02Hですから、この命令は08H 02Hとい うことになるわけです。 3:内部RAMのアクセスには次の様なものがあります。 (m),(BP+m),(BP-m),(PX+m),(PY-m),(BP+PX) (n),(BP+n),(BP-n),(PY+n),(PY-n),(BP+PY)  ニモニックの説明のところでは、これらを代表してnまたはmで表していま す。だだし、その命令のみがおかれた場合は(BP±n)と(BP±m)を意 味しています。これ以外のアドレッシングを行うには、命令の本体の前に次の 1バイトをおく必要があります。これをプレバイトといいます。プレバイトの 実行には1サイクルかかります。 +---------+---------+---------+---------+---------+ | 2| (n) | (BP n) | (PY n) | (BP+PY) | | 1 | | なし | | | +---------+---------+---------+---------+---------+ | (m) |  32H|  30H|  33H|  31H| | (BP m) |  22H|  なし |  23H|  21H| | (PX m) |  36H|  34H|  37H|  35H| | (BP+PX) |  26H|  24H|  27H|  25H| +---------+---------+---------+---------+---------+  なお、BPは内部RAMのアドレス&HECに、PX、PYはそれぞれ&H EDと&HECに割り当てられています。 例 1100 1100 m n :MV (m),n (8ビット)  ここで、MV (0D6H),01Hという命令があった場合、この(0D 6H)は上の表では(m)に当たります。また、2のほうはありませんから、 命令の本体の前に30Hをおく必要があります。そうするとさっきの命令は3 0H CCH D6H 01Hの4バイトということになります。  また、この表の1,2というのは、第1オペランド、第2オペランドという のとは関係ありません、従って第2オペランドに内部RAMのアクセスがある ときにも1の方を使うことがあります。 1110 1000 0000 0r3- n :MV [r3],(n) (8ビット)  この場合でMV [X],(0EBH)という命令を考えてみます。この場 合でも(0EBH)は1回目ですので(m)に相当します。(大混乱!)また 2の方はなしですので、プレバイトは30Hになります。  マイナスの値を表すときには2の補数を使います。そのためにオフセット値 は−128から+127までの範囲に限られます。 4:Pは符号を表し、0がプラス、1がマイナスを表します。 例 0001 001P :JR n  JR +16Hという場合、Pは0ですから、オペコードは0001001 0Bになります。従って、この命令は12H 16Hとなります。 5:サイクルはその命令を実行するのにかかる時間を表します。PC−E50 0シリーズではCPUを2.3MHzで動かしています。また1サイクルが3 クロックと仮定すると(実のところよくわからない)1サイクルは1.3ms に相当します。 a:MV命令  MV(MoVe)命令は、データの転送を行う命令です。レジスタに数値をいれ たり、メモリーにレジスタの内容をいれたりするときに使います。マシン語の プログラムでは一番たくさん使う命令です。  なお、レジスタに関係する命令のときは、みただけで何バイト転送するのか を判断できますが、内部RAMと外部のメモリーとの間でデータ転送を行う際 には、ニモニックだけでは、何バイトの転送命令なのか判断できません。その ためにこのときに限って、8ビット命令はMV、16ビット命令はMVW(W ordの略)、20ビット命令はMVP(Pointerの略)として区別し ます。  また、内部RAMに関してはIレジスタで表される回数だけを続けて実行す るMVL命令があるものもあります。  このCPUの場合、いろいろなアドレス指定の方法がありますので最初のう ちは混乱するかも知れませんが、慣れてくるといろいろ便利に使いこなせるよ うになるでしょう。それでは、MV命令をアドレス指定の方法でいくつかに分 類してみました。 a1:イミディエット(即値)  レジスタまたは内部RAMに、オペランドで示される値を直接代入します。 例 08 06 :MV A,06H  Aレジスタに4をいれます 0C 00 F0 0B :MV X,0BF000H  Xレジスタに0BF000Hを代入します。 CD 01 04 00 :MVW (BP+01H),04H  BP+01Hで表されるアドレスの内部RAM1ワードに0004Hをいれます。 書式 OPコード 1バイト目 2バイト以降 0000 1r1- n :MV r1,n (8ビット) 0000 1r2- n m :MV r2,mn (16ビット) 0000 1r3- n m l :MV r3,lmn (20ビット) プレバイトが付くこともある 1100 1100 m n :MV (m),n (8ビット) 1100 1101 l n m :MVW (l),mn (16ビット) 1101 1100 k n m l :MVP (k),lmn (20ビット) サイクル数 MV A,n 2サイクル (8ビット) MV IL,n 3サイクル (8ビット・実質は16ビット) MV r2,mn 3サイクル (16ビット) MV r3,lmn 4サイクル (20ビット) MV (m),n 3サイクル (8ビット) MVW (l),mn 4サイクル (16ビット) MVP (k),lmn 5サイクル (20ビット) a2:レジスタ間転送  レジスタ間でデータを転送します。当然のことながら、レジスタの大きさは同じでなければなりません。 例 75 :MV B,A  Aレジスタの内容をBレジスタに転送 FD 45 :MV X,Y  Yレジスタの内容をXレジスタに転送 書式 0111 0101 :MV B,A  (8ビットレジスタ間) 0111 0100 :MV A,B   (8ビットレジスタ間) 1111 1101 0r2- 0r2' :MV r2,r2' (16ビットレジスタ間) 1111 1101 0r3- 0r3' :MV r3,r3' (20ビットレジスタ間) サイクル数 MV B,A 1サイクル  (8ビットレジスタ間) MV A,B    1サイクル (8ビットレジスタ間) MV r2,r2' 2サイクル (16ビットレジスタ間) MV r3,r3' 2サイクル (20ビットレジスタ間) a3:内部RAMダイレクト/インダイレクトアドレッシング  レジスタまたは内部RAMと、オペランドで表されるアドレスの内部RAM (もしくは、BPなどのベースレジスタ+オフセットで表されるアドレス)と でデータの転送を行います。(n)は内部RAMをアクセスすることを示しま す。16ビット以上のレジスタに対しては、オペランドで表されるアドレス+ 1、20ビットのレジスタに対してはアドレス+2のデータも使われます。  内部RAM同士では、MVL、MVLD命令が存在します。MVL命令では、 1回の転送が終わるとそれぞれのアドレスを1づつ増やしながら、Iレジスタ で示される回数だけ転送を実行します。また、MVLD命令ではアドレスを1 づつ減らしながら指定回数転送します。(ブロック転送) 例 30 80 D6 :MV A,(0D6H)  Aレジスタに内部RAMの0D6Hの内容を転送します A4 D4 :MV (BP+0D4H),X  Xレジスタの内容を内部RAMのBP+04Hから3バイトに転送します 32 CB :MVL (01H),(08H)  内部RAMの01HからIレジスタで指定されているバイト数を内部RAM の08Hからに転送します 書式 プレバイトが付くこともある 1000 0r1- n :MV r1,(n) (8ビット) 1000 0r2- n :MV r2,(n) (16ビット) 1000 0r3- n :MV r3,(n) (20ビット) 1010 0r1- n :MV (n),r1 (8ビット) 1010 0r2- n :MV (n),r2 (16ビット) 1010 0r3- n :MV (n),r3 (20ビット) 1100 1000 m n :MV (m),(n) (8ビット) 1100 1001 m n :MVW (m),(n) (16ビット) 1100 1010 m n :MVP (m),(n) (20ビット) 1100 1011 m n :MVL (m),(n) (8ビットブロック転送) 1100 1111 m n :MVLD (m),(n) (8ビットブロック転送) サイクル数 MV A,(n) 3サイクル (8ビット) MV IL,(n) 4サイクル (8ビット・実質は16ビット) MV r2,(n) 4サイクル (16ビット) MV r3,(n) 5サイクル (20ビット) MV (n),r1 3サイクル (8ビット) MV (n),r2 4サイクル (16ビット) MV (n),r3 5サイクル (20ビット) MV (m),(n) 6サイクル (8ビット) MVW (m),(n) 8サイクル (16ビット) MVP (m),(n) 10サイクル (20ビット) MVL (m),(n) 5+2×Iサイクル(8ビットブロック転送) MVLD (m),(n) 5+2×Iサイクル(8ビットブロック転送) a4:ダイレクトアドレッシング  レジスタまたは内部RAMと、オペランドで表されるメモリーとの間で、デー タ転送を行います。  内部RAMに対するMVL命令では、1回の転送が終わるとそれぞれのアド レスを1づつ増やしながら、Iレジスタで示される回数だけ転送を実行します。 例 88 06 A0 00 :MV A,[0A006H]  0A006Hの内容をAレジスタに転送 30 D9 04 FC 0B :MVW [0BFC04H],(0D4H)  内部RAMの0D6Hから1ワードを0BFC04Hからへ転送 D3 00 00 0C 00 :MVL (BP+00H),[0C0000H]  内部RAMのBPからIレジスタで表されるバイト数分を0C0000Hからへ転送 書式 1000 1r1- n m l :MV r1,[lmn]  (8ビット) 1000 1r2- n m l :MV r2,[lmn]  (16ビット) 1000 1r3- n m l :MV r3,[lmn]  (20ビット) 1010 1r1- n m l :MV [lmn],r1  (8ビット) 1010 1r2- n m l :MV [lmn],r2  (16ビット) 1010 1r3- n m l :MV [lmn],r3  (20ビット) プレバイトが付くこともある 1101 0000 k n m l :MV (k),[lmn] (8ビット) 1101 0001 k n m l :MVW (k),[lmn] (16ビット) 1101 0010 k n m l :MVP (k),[lmn] (20ビット) 1101 0011 k n m l :MVL (k),[lmn] (8ビットブロック転送) 1101 1000 m l k n :MV [klm],(n) (8ビット) 1101 1001 m l k n :MVW [klm],(n) (16ビット) 1101 1010 m l k n :MVP [klm],(n) (20ビット) 1101 1011 m l k n :MVL [klm],(n) (8ビットブロック転送) サイクル数 MV r1,[lmn] 6サイクル   (8ビット) MV r2,[lmn]  7サイクル (16ビット) MV r3,[lmn]  8サイクル (20ビット) MV [lmn],r1  5サイクル (8ビット) MV [lmn],r2  6サイクル (16ビット) MV [lmn],r3  7サイクル (20ビット) MV (k),[lmn]  7サイクル (8ビット) MVW (k),[lmn]  8サイクル (16ビット) MVP (k),[lmn]  9サイクル (20ビット) MVL (k),[lmn]  6+2×Iサイクル (8ビットブロック転送) MV [klm],(n)  6サイクル (8ビット) MVW [klm],(n)  7サイクル (16ビット) MVP [klm],(n)  8サイクル (20ビット) MVL [klm],(n)  6+2×Iサイクル (8ビットブロック転送) a5:ポインタ・レジスタ間接  レジスタまたは内部RAMと、ポインタ・レジスタの内容が示すアドレスの メモリーとの間で、データ転送を行います。ポインタ・レジスタとは、20ビッ トの幅を持つX、Y、U、Sのことです。 例 94 05 :MV X,[Y]  Yレジスタで示されるアドレスのメモリーの内容をXレジスタに転送します 36 EA 06 04 :MVP [U],(PX+04H)  内部RAMのPX+04Hから20bitをUレジスタで示されるアドレス へ転送します 書式 1001 0r1- 0000 0r3' :MV r1,[r3'] (8ビット) 1001 0r2- 0000 0r3' :MV r2,[r3'] (16ビット) 1001 0r4- 0000 0r3' :MV r4,[r3'] (20ビット) 1011 0r1- 0000 0r3' :MV [r3'],r1 (8ビット) 1011 0r2- 0000 0r3' :MV [r3'],r2 (16ビット) 1011 0r4- 0000 0r3' :MV [r3'],r4 (20ビット) プレバイトが付くこともある 1110 0000 0000 0r3- n :MV (n),[r3] (8ビット) 1110 0001 0000 0r3- n :MVW (n),[r3] (16ビット) 1110 0010 0000 0r3- n :MVP (n),[r3] (20ビット) 1110 1000 0000 0r3- n :MV [r3],(n) (8ビット) 1110 1001 0000 0r3- n :MVW [r3],(n) (16ビット) 1110 1010 0000 0r3- n :MVP [r3],(n) (20ビット) サイクル数 MV A,[r3'] 4サイクル (8ビット) MV IL,[r3'] 5サイクル (8ビット・実質は16ビット) MV r2,[r3'] 5サイクル (16ビット) MV r4,[r3'] 6サイクル (20ビット) MV [r3'],r1 4サイクル (8ビット) MV [r3'],r2 5サイクル (16ビット) MV [r3'],r4 6サイクル (20ビット) MV (n),[r3] 6サイクル (8ビット) MVW (n),[r3] 7サイクル (16ビット) MVP (n),[r3] 8サイクル (20ビット) MV [r3],(n) 6サイクル (8ビット) MVW [r3],(n) 7サイクル (16ビット) MVP [r3],(n) 8サイクル (20ビット) a6:ポストインクリメント付きレジスタ間接  ポンイタ・レジスタ間接と同じく、レジスタまたは内部RAMとポインタ・ レジスタの内容が示すメモリーとの間でデータ転送を行いますが、データ転送 が終わった後でポインタ・レジスタの値をデータが使用されたバイト数だけ (8ビットなら1、16ビットなら2、20ビットなら3)増やします。  内部RAMに関するMVL命令では、1回の転送が終わるとそれぞれのアド レスを1づつ増やしながら、Iレジスタで示される回数だけ転送を実行します。 例 94 25 :MV X,[Y++]  Yレジスタで示されるアドレスのメモリーの内容をXレジスタに転送し、そ の後でYレジスタに3を足します 36 EA 26 04 :MVP [U++],(PX+04H)  内部RAMのPX+04Hから20bitをUレジスタで示されるアドレス へ転送し、その後でUレジスタに3を足します 書式 1001 0r1- 0010 0r3' :MV r1,[r3'++] (8ビット) 1001 0r2- 0010 0r3' :MV r2,[r3'++] (16ビット) 1001 0r4- 0010 0r3' :MV r4,[r3'++] (20ビット) 1011 0r1- 0010 0r3' :MV [r3'++],r1 (8ビット) 1011 0r2- 0010 0r3' :MV [r3'++],r2 (16ビット) 1011 0r4- 0010 0r3' :MV [r3'++],r4 (20ビット) プレバイトが付くこともある 1110 0000 0010 0r3- n :MV (n),[r3++] (8ビット) 1110 0001 0010 0r3- n :MVW (n),[r3++] (16ビット) 1110 0010 0010 0r3- n :MVP (n),[r3++] (20ビット) 1110 0011 0010 0r3- n :MVL (n),[r3++] (ブロック転送) 1110 1000 0010 0r3- n :MV [r3++],(n) (8ビット) 1110 1001 0010 0r3- n :MVW [r3++],(n) (16ビット) 1110 1010 0010 0r3- n :MVP [r3++],(n) (20ビット) 1110 1011 0010 0r3- n :MVL [r3++],(n) (ブロック転送) サイクル数 MV A,[r3'++] 4サイクル (8ビット) MV IL,[r3'++] 5サイクル (8ビット・実質は16ビット) MV r2,[r3'++] 5サイクル (16ビット) MV r4,[r3'++] 7サイクル (20ビット) MV [r3'++],r1 4サイクル (8ビット) MV [r3'++],r2 5サイクル (16ビット) MV [r3'++],r4 7サイクル (20ビット) MV (n),[r3++] 6サイクル (8ビット) MVW (n),[r3++] 7サイクル (16ビット) MVP (n),[r3++] 9サイクル (20ビット) MVL (n),[r3++] 5+2×Iサイクル (ブロック転送) MV [r3++],(n) 6サイクル (8ビット) MVW [r3++],(n) 7サイクル (16ビット) MVP [r3++],(n) 9サイクル (20ビット) MVL [r3++],(n) 5+2×Iサイクル (ブロック転送) a7:プレデクリメント付きレジスタ間接  ポンイタ・レジスタ間接と同じく、レジスタまたは内部RAMとポインタ・ レジスタの内容が示すメモリーとの間でデータ転送を行いますが、データ転送 を行う前にポインタ・レジスタの値をデータを使用するバイト数だけ(8ビッ トなら1、16ビットなら2、20ビットなら3)へらして、変更された値を 基準にしてデータ転送をします。  内部RAMに関するMVL命令では、1回の転送を行う前にポインタのアド レスを、転送を行った後で内部RAMのアドレスを1づつ減らし、Iレジスタ で示される回数だけ転送を実行します。 例 94 35 :MV X,[--Y]  Yレジスタから3を引いた後で、Yレジスタで示されるアドレスのメモリー の内容をXレジスタに転送します 36 EA 36 04 :MVP [--U],(PX+04H)  Uレジスタから3を引いた後で、内部RAMのPX+04Hから20bit をUレジスタで示されるアドレスへ転送します 書式 1001 0r1- 0011 0r3' :MV r1,[--r3'] (8ビット) 1001 0r2- 0011 0r3' :MV r2,[--r3'] (16ビット) 1001 0r4- 0011 0r3' :MV r4,[--r3'] (20ビット) 1011 0r1- 0011 0r3' :MV [--r3'],r1 (8ビット) 1011 0r2- 0011 0r3' :MV [--r3'],r2 (16ビット) 1011 0r4- 0011 0r3' :MV [--r3'],r4 (20ビット) プレバイトが付くこともある 1110 0000 0011 0r3- n :MV (n),[--r3] (8ビット) 1110 0001 0011 0r3- n :MVW (n),[--r3] (16ビット) 1110 0010 0011 0r3- n :MVP (n),[--r3] (20ビット) 1110 0011 0011 0r3- n :MVL (n),[--r3]  (ブロック転送) 1110 1000 0011 0r3- n :MV [--r3],(n) (8ビット) 1110 1001 0011 0r3- n :MVW [--r3],(n) (16ビット) 1110 1010 0011 0r3- n :MVP [--r3],(n) (20ビット) 1110 1011 0011 0r3- n :MVL [--r3],(n)  (ブロック転送) サイクル数 MV A,[--r3'] 5サイクル (8ビット) MV IL,[--r3'] 6サイクル (8ビット・実質は16ビット) MV r2,[--r3'] 6サイクル (16ビット) MV r4,[--r3'] 8サイクル (20ビット) MV [--r3'],r1 5サイクル (8ビット) MV [--r3'],r2 6サイクル (16ビット) MV [--r3'],r4 8サイクル (20ビット) MV (n),[--r3] 7サイクル (8ビット) MVW (n),[--r3] 10サイクル (16ビット) MVP (n),[--r3] 10サイクル (20ビット) MVL (n),[--r3] 7+2×Iサイクル(ブロック転送) MV [--r3],(n) 7サイクル (8ビット) MVW [--r3],(n) 10サイクル (16ビット) MVP [--r3],(n) 10サイクル (20ビット) MVL [--r3],(n) 7+2×Iサイクル(ブロック転送) a8:ポインタ・レジスタ・ベースアドレッシング  レジスタまたは内部RAMとポインタレジスタの内容にオフセット値を加え て表されるアドレスのメモリーとの間で、データ転送を行います。オフセット 値は±255までに限られます。  内部RAMに関するMVL命令では、1回の転送が終わるとそれぞれのアド レスを1づつ増やしながら、Iレジスタで示される回数だけ転送を実行します。 例 94 85 02 :MV X,[Y+02H]  Yレジスタの内容+02Hで示されるアドレスのメモリーの内容をXレジス タに転送します 36 EA C6 03 04 :MVP [U-03H],(PX+04H)  内部RAMのPX+04Hから20bitをUレジスタの内容−03Hで示 されるアドレスへ転送します 書式 1001 0r1- 1P00 0r3' n :MV r1,[r3' n] (8ビット) 1001 0r2- 1P00 0r3' n :MV r2,[r3' n] (16ビット) 1001 0r4- 1P00 0r3' n :MV r4,[r3' n] (20ビット) 1011 0r1- 1P00 0r3' n :MV [r3' n],r1 (8ビット) 1011 0r2- 1P00 0r3' n :MV [r3' n],r2 (16ビット) 1011 0r4- 1P00 0r3' n :MV [r3' n],r4 (20ビット) プレバイトが付くこともある 1110 0000 1P00 0r3- m n :MV (m),[r3 n] (8ビット) 1110 0001 1P00 0r3- m n :MVW (m),[r3 n] (16ビット) 1110 0010 1P00 0r3- m n :MVP (m),[r3 n] (20ビット) 0101 0110 1P00 0r3- m n :MVL (m),[r3 n] (ブロック転送) 1110 1000 1P00 0r3- n m :MV [r3 m],(n) (8ビット) 1110 1001 1P00 0r3- n m :MVW [r3 m],(n) (16ビット) 1110 1010 1P00 0r3- n m :MVP [r3 m],(n) (20ビット) 0101 1110 1P00 0r3- n m :MVL [r3 m],(n) (ブロック転送) サイクル数 MV A,[r3' n] 6サイクル (8ビット) MV IL,[r3' n] 7サイクル (8ビット・実質は16ビット) MV r2,[r3' n] 7サイクル (16ビット) MV r4,[r3' n] 8サイクル (20ビット) MV [r3' n],r1 6サイクル (8ビット) MV [r3' n],r2 7サイクル (16ビット) MV [r3' n],r4 8サイクル (20ビット) MV (m),[r3 n] 8サイクル (8ビット) MVW (m),[r3 n] 9サイクル (16ビット) MVP (m),[r3 n] 10サイクル (20ビット) MVL (m),[r3 n] 5+2×Iサイクル(ブロック転送) MV [r3 m],(n) 8サイクル (8ビット) MVW [r3 m],(n) 9サイクル (16ビット) MVP [r3 m],(n) 10サイクル (20ビット) MVL [r3 m],(n) 5+2×Iサイクル(ブロック転送) a9:内部RAM間接  レジスタまたは内部RAMと、内部RAMの内容が示すアドレスのメモリー との間で、データ転送を行います。  内部RAMに関するMVL命令では、1回の転送が終わるとそれぞれのアド レスを1づつ増やしながら、Iレジスタで示される回数だけ転送を実行します。 例 9B 00 06 :MV I,[(BP+06H)]  Iレジスタに内部RAMのBP+06Hで示されるアドレスのメモリー内容を転送します 37 FA 00 02 FC :MVP [(PX+02H)],(PY-04H)  内部RAMのPX+02Hで示されるアドレスのメモリーに内部RAMのPX−04Hからの20ビットを転送します 書式 1001 1r1- 0000 0000 n :MV r1,[(n)] (8ビット) 1001 1r2- 0000 0000 n :MV r2,[(n)] (16ビット) 1001 1r4- 0000 0000 n :MV r4,[(n)] (20ビット) 1011 1r1- 0000 0000 n :MV [(n)],r1 (8ビット) 1011 1r2- 0000 0000 n :MV [(n)],r2 (16ビット) 1011 1r4- 0000 0000 n :MV [(n)],r4 (20ビット) プレバイトが付くこともある 1111 0000 0000 0000 m n :MV (m),[(n)] (8ビット) 1111 0001 0000 0000 m n :MVW (m),[(n)] (16ビット) 1111 0010 0000 0000 m n :MVP (m),[(n)] (20ビット) 1111 0011 0000 0000 m n :MVL (m),[(n)] (ブロック転送) 1111 1000 0000 0000 m n :MV [(m)],(n) (8ビット) 1111 1001 0000 0000 m n :MVW [(m)],(n) (16ビット) 1111 1010 0000 0000 m n :MVP [(m)],(n) (20ビット) 1111 1011 0000 0000 m n :MVL [(m)],(n) (ブロック転送) サイクル数 MV A,[(n)] 9サイクル (8ビット) MV IL,[(n)] 10サイクル (8ビット・実質は16ビット) MV r2,[(n)] 10サイクル (16ビット) MV r4,[(n)] 11サイクル (20ビット) MV [(n)],r1 9サイクル (8ビット) MV [(n)],r2 10サイクル (16ビット) MV [(n)],r4 11サイクル (20ビット) MV (m),[(n)] 11サイクル (8ビット) MVW (m),[(n)] 12サイクル (16ビット) MVP (m),[(n)] 13サイクル (20ビット) MVL (m),[(n)] 10+2×Iサイクル(ブロック転送) MV [(m)],(n) 11サイクル (8ビット) MVW [(m)],(n) 12サイクル (16ビット) MVP [(m)],(n) 13サイクル (20ビット) MVL [(m)],(n) 10+2×Iサイクル(ブロック転送) a10:内部RAM・ベースアドレッシング  レジスタまたは内部RAMと内部RAMの内容にオフセット値を加えて表さ れるアドレスのメモリーとの間で、データ転送を行います。内部RAMに関す るMVL命令では、1回の転送が終わるとそれぞれのアドレスを1づつ増やし ながら、Iレジスタで示される回数だけ転送を実行します。 例 9B C0 06 10 :MV I,[(BP+06H)-10H]  内部RAMのBP+06Hの内容−10Hで示されるアドレスのメモリー内 容をIレジスタに転送します 37 FA 80 02 40 FC :MVP [(PX+02H)+40H],(PY-04H)  内部RAMのPX+02Hの内容+40Hで示されるアドレスのメモリーに 内部RAMのPX−04Hからの20ビットを転送します 書式 1001 1r1- 1P00 0000 m n :MV r1,[(m) n] (8ビット) 1001 1r2- 1P00 0000 m n :MV r2,[(m) n] (16ビット) 1001 1r4- 1P00 0000 m n :MV r4,[(m) n] (20ビット) 1011 1r1- 1P00 0000 m n :MV [(m) n],r1 (8ビット) 1011 1r2- 1P00 0000 m n :MV [(m) n],r2 (16ビット) 1011 1r4- 1P00 0000 m n :MV [(m) n],r4 (20ビット) プレバイトが付くこともある 1111 0000 1P00 0000 l m n :MV (l),[(m) n] (8ビット) 1111 0001 1P00 0000 l m n :MVW (l),[(m) n] (16ビット) 1111 0010 1P00 0000 l m n :MVP (l),[(m) n] (20ビット) 1111 0011 1P00 0000 l m n :MVL (l),[(m) n] (ブロック転送) 1111 1000 1P00 0000 l m n :MV [(l) m],(n) (8ビット) 1111 1001 1P00 0000 l m n :MVW [(l) m],(n) (16ビット) 1111 1010 1P00 0000 l m n :MVP [(l) m],(n) (20ビット) 1111 1011 1P00 0000 l m n :MVL [(l) m],(n) (ブロック転送) サイクル数 MV A,[(m) n] 11サイクル (8ビット) MV IL,[(m) n] 12サイクル (8ビット・実質は16ビット) MV r2,[(m) n] 12サイクル (16ビット) MV r4,[(m) n] 13サイクル (20ビット) MV [(m) n],r1 11サイクル (8ビット) MV [(m) n],r2 12サイクル (16ビット) MV [(m) n],r4 13サイクル (20ビット) MV (l),[(m) n] 13サイクル (8ビット) MVW (l),[(m) n] 14サイクル (16ビット) MVP (l),[(m) n] 15サイクル (20ビット) MVL (l),[(m) n] 12+2×Iサイクル(ブロック転送) MV [(l) m],(n) 13サイクル (8ビット) MVW [(l) m],(n) 14サイクル (16ビット) MVP [(l) m],(n) 15サイクル (20ビット) MVL [(l) m],(n) 12+2×Iサイクル(ブロック転送) b)データ交換命令 b1:EX命令  EX(EXcahge)命令はレジスタ間または内部RAM同士で、データの交換 をします。MV命令の場合転送されるレジスタの内容が破壊されてしまいます が、EX命令では単純に入れ替わるだけです。内部RAMに関するEXL命令 では、1回の交換が終わるとそれぞれのアドレスを1づつ増やしながら、Iレ ジスタで示される回数だけ交換を実行します。 例 ED 32 :EX I,BA  IレジスタとBAレジスタの内容を入れ換えます 書式 1101 1101 :EX A,B (8ビットレジスタ間) 1110 1101 0r2- 0r2' :EX r2,r2' (16ビットレジスタ間) 1110 1101 0r3- 0r3' :EX r3,r3' (20ビットレジスタ間) プレバイトが付くこともある 1100 0000 m n :EX (m),(n) (8ビット) 1100 0001 m n :EXW (m),(n) (16ビット) 1100 0010 m n :EXP (m),(n) (20ビット) 1100 0011 m n :EXL (m),(n) (ブロック交換) サイクル数 EX A,B 3サイクル (8ビットレジスタ間) EX r2,r2' 4サイクル (16ビットレジスタ間) EX r3,r3' 4サイクル (20ビットレジスタ間) EX (m),(n) 7サイクル (8ビット) EXW (m),(n) 10サイクル (16ビット) EXP (m),(n) 13サイクル (20ビット) EXL (m),(n) 5+3×Iサイクル(ブロック交換) b2:SWAP命令  SWAP命令は、Aレジスタの上位4ビットと下位4ビットを交換します。 Zフラグが影響を受けます。 書式 1110 1110 : SWAP A サイクル数:3サイクル c)算術演算命令  足し算、引き算をする命令です。ADD、ADC、SUB、SBC、ADC L、DADL、SBCL、DSBL、PMDFなどの命令があります。残念な がらかけ算や割り算をする命令はありません。これらの命令は、PMDFを除 き演算結果に伴って、Cフラグ、Zフラグに影響を受けます。 c1:ADD命令  ADD(ADDition)命令は足し算を行う命令です。結果は第1オペランドに 入ります。レジスタ同士のADD命令ではレジスタの大きさが同じである必要 はありません。しかし、結果をいれるレジスタの方が大きくなければなりませ ん。 例 40 04 :ADD A,04H Aレジスタの内容に4を足します。結果はAレジスタに入ります 45 45 :ADD X,Y Xレジスタの内容にYレジスタの内容を足します。結果はXレジスタに入ります 書式 0100 0000 n :ADD A,n (アキュムレータ即値) 0100 0001 m n :ADD (m),n (内部RAM即値) 0100 0011 n :ADD (n),A (アキュムレータ内部RAM) 0100 0010 n :ADD A,(n) (内部RAMアキュムレータ) 0100 0110 0r1- 0r1' :ADD r1,r1' (8ビットレジスタ間) 0100 0100 0r2- 0r1' :ADD r2,r1' (16ビットレジスタ) 0100 0100 0r2- 0r2' :ADD r2,r2' (16ビットレジスタ間) 0100 0101 0r3- 0r'- :ADD r3,r' (20ビットレジスタ) サイクル数 ADD A,n 3サイクル (アキュムレータ即値) ADD (m),n 4サイクル (内部RAM即値) ADD (n),A 4サイクル (アキュムレータ内部RAM) ADD A,(n) 4サイクル (内部RAMアキュムレータ) ADD r1,r1' 3サイクル (8ビットレジスタ間) ADD r2,r1' 5サイクル (16ビットレジスタ) ADD r2,r2' 5サイクル (16ビットレジスタ間) ADD r3,r' 7サイクル (20ビットレジスタ) c2:ADC命令  ADC(ADdition with Carry)命令はADDと同じく足し算を行う命令で すが、その前にCフラグが1であったなら、さらに1を余分に足します。一般 には多数桁の数値の足し算に用いられます。レジスタ間の命令はありません。 例 50 04 :ADC A,04H Aレジスタの内容に4を足し、さらにCフラグが1であったなら1を余分に 足します。結果はAレジスタに入ります 書式 0101 0000 n :ADC A,n (アキュムレータ即値) 0101 0001 m n :ADC (m),n (内部RAM即値) 0101 0011 n :ADC (n),A (アキュムレータ内部RAM) 0101 0010 n :ADC A,(n) (内部RAMアキュムレータ) サイクル数 ADC A,n 3サイクル(アキュムレータ即値) ADC (m),n 4サイクル(内部RAM即値) ADC (n),A 4サイクル(アキュムレータ内部RAM) ADC A,(n) 4サイクル(内部RAMアキュムレータ) c3:SUB命令  SUB(SUBtract)命令は引き算を行う命令です。結果は第1オペランドに 入ります。レジスタ同士のSUB命令ではレジスタの大きさが同じである必要 はありません。しかし、結果をいれるレジスタの方が大きくなければなりませ ん。 例 48 04 :SUB A,04H Aレジスタの内容から4を引きます。結果はAレジスタに入ります 4D 45 :SUB X,Y Xレジスタの内容からYレジスタの内容を引きます。結果はXレジスタに入ります 書式 0100 1000 n :SUB A,n (アキュムレータ即値) 0100 1001 m n :SUB (m),n (内部RAM即値) 0100 1011 n :SUB (n),A (アキュムレータ内部RAM) 0100 1010 n :SUB A,(n) (内部RAMアキュムレータ) 0100 1110 0r1- 0r1' :SUB r1,r1' (8ビットレジスタ間) 0100 1100 0r2- 0r1' :SUB r2,r1' (16ビットレジスタ) 0100 1100 0r2- 0r2' :SUB r2,r2' (16ビットレジスタ間) 0100 1101 0r3- 0r'- :SUB r3,r' (20ビットレジスタ) サイクル数 SUB A,n 3サイクル(アキュムレータ即値) SUB (m),n 4サイクル(内部RAM即値) SUB (n),A 4サイクル(アキュムレータ内部RAM) SUB A,(n) 4サイクル(内部RAMアキュムレータ) SUB r1,r1' 3サイクル(8ビットレジスタ間) SUB r2,r1' 5サイクル(16ビットレジスタ) SUB r2,r2' 5サイクル(16ビットレジスタ間) SUB r3,r' 7サイクル(20ビットレジスタ) c4:SBC命令  SBC(SuBtract with Carry)命令は引き算を行う命令ですが、その前に Cフラグが1であったなら、さらに1を余分に引きます。レジスタ間の命令は ありません。 例 58 04 :SBC A,04H Aレジスタの内容から4を引き、さらにCフラグが1であったなら1を余分 に引きます。結果はAレジスタに入ります 書式 0101 1000 n :SBC A,n (アキュムレータ即値) 0101 1001 m n :SBC (m),n (内部RAM即値) 0101 1011 n :SBC (n),A (アキュムレータ内部RAM) 0101 1010 n :SBC A,(n) (内部RAMアキュムレータ) サイクル数 SBC A,n 3サイクル(アキュムレータ即値) SBC (m),n 4サイクル(内部RAM即値) SBC (n),A 4サイクル(アキュムレータ内部RAM) SBC A,(n) 4サイクル(内部RAMアキュムレータ) c5:ADCL命令  ADCL(ADdition with Carry Loop)は内部RAMに存在する多数桁の数 値に対して、足し算を行う命令です。バイト数はIレジスタに格納しておきま す。 書式 0101 0100 m n :ADCL (m),(n) (内部RAM間ブロック加算) 0101 0101 n :ADCL (n),A (内部RAMブロックにAの値を加算) サイクル数 ADCL (m),(n) 5+2×Iサイクル(内部RAM間ブロック加算) ADCL (n),A 4+Iサイクル (内部RAMブロックにAの値を加算) c6:SBCL命令  SBCL(SuBtract with Carry Loop)は内部RAMに存在する多数桁の数 値に対して、引き算を行う命令です。バイト数はIレジスタに格納しておきま す。 書式 0101 1100 m n :SBCL (m),(n) (内部RAM間ブロック減算) 0101 1101 n :SBCL (n),A (内部RAMブロックからAの値を減算) サイクル数 SBCL (m),(n) 5+2×Iサイクル(内部RAM間ブロック減算) SBCL (n),A 4+Iサイクル (内部RAMブロックからAの値を減算) c7:DADL命令  DADL(Decimal ADdition Loop)命令は内部RAMに存在するBCDで 表された多数桁の数値に対して、10進で足し算を行います。BCDというの は2進化10進数ともいいます。普通2進数4桁で16進数を表しますがこの ときAからFまでを使わないようにすれば10進数とみることもできます。こ れをBCDといいます。従って1000Hは普通は4096を表しますが、B CDでは1000を表します。  バイト数(BCD2桁で1バイト)はIレジスタに格納しておきます。 書式 1100 0100 m n :DADL (m),(n) (内部RAM間ブロック加算) 1100 0101 n :DADL (n),A (内部RAMブロックにAの値を加算) サイクル数 DADL (m),(n) 5+2×Iサイクル(内部RAM間ブロック加算) DADL (n),A 4+Iサイクル (内部RAMブロックにAの値を加算) c8:DSBL命令  DSBL(Decimal SuBtract Loop)命令は内部RAMに存在するBCD (2進化10進数)で表された多数桁の数値に対して、10進で引き算を行い ます。バイト数はIレジスタに格納しておきます。 書式 1101 0100 m n :DSBL (m),(n) (内部RAM間ブロック減算) 1101 0101 n :DSBL (n),A (内部RAMブロックからAの値を減算) サイクル数 DSBL (m),(n) 5+2×Iサイクル(内部RAM間ブロック減算) DSBL (n),A 4+Iサイクル (内部RAMブロックからAの値を減算) c9:PMDF命令  PMDF(Pointer MoDiFy)命令は内部RAMの値にAレジスタの値もしく は即値を足します。ただし、ほかの算術命令とは異なり、フラグは変化しませ ん。 書式 0100 0111 m n :PMDF (m),n (即値) 0101 0111 n :PMDF (n),A (Aレジスタ) サイクル数  どちらも4サイクル d)論理演算命令  論理演算命令は、数値を2進数にして各ビット毎に論理演算をする命令です。 AND(論理積)、OR(論理和)、XOR(排他的論理和)の3種の命令が あります。 d1:AND命令  AND命令は、8ビットの数値に対して論理積をとる命令です。論理積とは、 真理値表では次のように表されます。 +---+---+---------------+ | X| Y| X AND Y| +---+---+---------------+ | 0| 0| 0 | | 0| 1| 0 | | 1| 0| 0 | | 1| 1| 1 | +---+---+---------------+  つまり、両方のビットが1であったときのみ答えが1になるわけです。この 演算を各ビットに対して行います。従ってAND命令はビットマスク(計算に 関係のないビットを0にすること)によく使われます。演算結果によってZフ ラグが影響を受けます。 書式 0111 0000 n :AND A,n   (アキュムレータに即値) 0111 0001 m n :AND (m),n (内部RAMに即値) 0111 0010 m l k n :AND [klm],n (外部メモリーに即値) 0111 0011 n :AND (n),A (内部RAMにアキュムレータ) 0111 0111 n :AND A,(n) (アキュムレータに内部RAM) 0111 0110 m n :AND (m),(n) (内部RAM間) サイクル数 AND A,n 3サイクル (アキュムレータに即値) AND (m),n 4サイクル (内部RAMに即値) AND [klm],n 7サイクル (外部メモリーに即値) AND (n),A 4サイクル (内部RAMにアキュムレータ) AND A,(n) 4サイクル (アキュムレータに内部RAM) AND (m),(n) 6サイクル (内部RAM間) d2:OR命令  OR命令は、8ビットの数値に対して論理和をとる命令です。論理和とは、 真理値表では次のように表されます。 +---+---+---------------+ | X| Y| X  OR  Y| +---+---+---------------+ | 0| 0| 0 | | 0| 1| 1 | | 1| 0| 1 | | 1| 1| 1 | +---+---+---------------+  つまり、元のどちらかのビットが1であれば、答えが1になるわけです。こ の演算を各ビットに対して行います。OR命令はビットのセットによく使われ ます。演算結果によってZフラグが影響を受けます。 書式 0111 1000 n :OR A,n   (アキュムレータに即値) 0111 1001 m n :OR (m),n (内部RAMに即値) 0111 1010 m l k n :OR [klm],n (外部メモリーに即値) 0111 1011 n :OR (n),A (内部RAMにアキュムレータ) 0111 1111 n :OR A,(n) (アキュムレータに内部RAM) 0111 1110 m n :OR (m),(n) (内部RAM間) サイクル数 OR A,n 3サイクル (アキュムレータに即値) OR (m),n 4サイクル (内部RAMに即値) OR [klm],n 7サイクル (外部メモリーに即値) OR (n),A 4サイクル (内部RAMにアキュムレータ) OR A,(n) 4サイクル (アキュムレータに内部RAM) OR (m),(n) 6サイクル (内部RAM間) d3:XOR命令  XOR(eXclusive OR)命令は、8ビットの数値に対して排他的論理和をと る命令です。排他的論理和とは、真理値表では次のように表されます。 +---+---+---------------+ | X| Y| X XOR Y| +---+---+---------------+ | 0| 0| 0 | | 0| 1| 1 | | 1| 0| 1 | | 1| 1| 0 | +---+---+---------------+  OR命令と違うのは、元のビットの両方が1であったときに、答えが0にな ることです。この演算を各ビットに対して行います。演算結果によってZフラ グが影響を受けます。 書式 0110 1000 n :XOR A,n   (アキュムレータに即値) 0110 1001 m n :XOR (m),n (内部RAMに即値) 0110 1010 m l k n :XOR [klm],n (外部メモリーに即値) 0110 1011 n :XOR (n),A (内部RAMにアキュムレータ) 0110 1111 n :XOR A,(n) (アキュムレータに内部RAM) 0110 1110 m n :XOR (m),(n) (内部RAM間) サイクル数 XOR A,n 3サイクル (アキュムレータに即値) XOR (m),n 4サイクル (内部RAMに即値) XOR [klm],n 7サイクル (外部メモリーに即値) XOR (n),A 4サイクル (内部RAMにアキュムレータ) XOR A,(n) 4サイクル (アキュムレータに内部RAM) XOR (m),(n) 6サイクル (内部RAM間) e)インクリメント、デクリメント命令 e1:INC命令  INC(INCriment)命令は、レジスタまたは内部RAMに対し、その内容 を1増やします。但し、影響を受けるのはZフラグのみであり、たとえオーバー フローを起こしてもCフラグは影響を受けないので注意が必要です。 書式 0110 1100 0000 0r-- :INC r   (レジスタ) 0110 1101 m :INC (m) (内部RAM) サイクル数  どちらも3サイクル e2:DEC命令  DEC(DECriment)命令は、レジスタまたは内部RAMに対し、その内容 を1減らします。但し、影響を受けるのはZフラグのみであり、たとえアンダー フローを起こしてもCフラグは影響を受けないので注意が必要です。 書式 0111 1100 0000 0r-- :DEC r   (レジスタ) 0111 1101 m :DEC (m) (内部RAM) サイクル数  どちらも3サイクル f)ローテイト、シフト命令  ローテイト、シフト命令は8ビットの数値に対して、ビットの回転、移動を 行う命令です。また、多数桁の数値に対して、4ビットづつずらす命令もあり ます。 f1:ROR命令  ROR(ROtate to Right)命令は、ビットの右回転を行います。次の図を みて下さい。 ← 移動の方向 +-------------------------------------+ | 7 6 5 4 3 2 1 0 | C | +---+---+---+---+---+---+---+---+ | +---+ +-+ | | | | | | | +---+---+ | +---+---+---+---+---+---+---+---+ +---+   移動の方向 →  第1ビットの内容が、第0ビットにというように、各ビットの内容が、右ど なりのビットに移されるわけです。そして、第0ビットにあった内容は、第7 ビットに移されます。演算の結果、ZフラグとCフラグが影響を受けますが、 Cフラグは、元の第0ビットの内容と同じになります。 書式 1110 0100 :ROR A   (アキュムレータ) 1110 0101 n :ROR (n) (内部RAM) サイクル数 ROR A 2サイクル (アキュムレータ) ROR (n) 3サイクル (内部RAM) f2:ROL命令  ROL(ROtate to Left)命令は、ビットの左回転を行います。次の図をみ て下さい。 移動の方向 → +-------------------------------------+ C | 7 6 5 4 3 2 1 0 | +---+ | +---+---+---+---+---+---+---+---+ | | +---+---+ | | | | | | | +-+ +---+ +---+---+---+---+---+---+---+---+   ← 移動の方向  第6ビットの内容が、第7ビットにというように、各ビットの内容が、左ど なりのビットに移されるわけです。そして、第7ビットにあった内容は、第0 ビットに移されます。演算の結果、ZフラグとCフラグが影響を受けますが、 Cフラグは、元の第7ビットの内容と同じになります。 書式 1110 0110 :ROL A   (アキュムレータ) 1110 0111 n :ROL (n) (内部RAM) サイクル数 ROL A 2サイクル (アキュムレータ) ROL (n) 3サイクル (内部RAM) f3:SHR命令  SHR(SHift to Right)命令は、ビットの右シフトを行います。次の図を みて下さい。 ← 移動の方向 +---------------------------------------------+ | 7 6 5 4 3 2 1 0 C | | +---+---+---+---+---+---+---+---+ +---+ | +-+ | | | | | | | +-----+ +-+ +---+---+---+---+---+---+---+---+ +---+   移動の方向 →  第1ビットの内容が、第0ビットにというように、各ビットの内容が、右ど なりのビットに移されるわけです。ROR命令と違って、第0ビットにあった 内容は、Cフラグに移されるのみで、元のCフラグの内容が第7ビットに移さ れます。SHR命令は一般に数値を2で割りたいときに用いられます。演算の 結果、ZフラグとCフラグが影響を受けます。 書式 1111 0100 :SHR A   (アキュムレータ) 1111 0101 n :SHR (n) (内部RAM) サイクル数 SHR A 2サイクル (アキュムレータ) SHR (n) 3サイクル (内部RAM) f4:SHL命令  SHL(SHift to Left)命令は、ビットの左シフトを行います。次の図を みて下さい。 移動の方向 → +-------------------------------------------+ | C 7 6 5 4 3 2 1 0 | | +---+ +---+---+---+---+---+---+---+---+ | +-+ +---+ | | | | | | | +-+ +---+ +---+---+---+---+---+---+---+---+   ← 移動の方向  第6ビットの内容が、第7ビットにというように、各ビットの内容が、左ど なりのビットに移されるわけです。第7ビットにあった内容は、ROL命令と 異なりCフラグに移されるだけです。そして、元のCフラグの内容が第0ビッ トに移されます。一般にSHL命令は、数値を2倍するときに良く用いられま す。演算の結果、ZフラグとCフラグが影響を受けます。 書式 1111 0110 :SHL A   (アキュムレータ) 1111 0111 n :SHL (n)   (内部RAM) サイクル数 SHL A 2サイクル (アキュムレータ) SHL (n) 3サイクル (内部RAM) f5:DSRL命令  DSRL(Decimal Shift to Right Loop ?)命令は、内部RAMに存在す るIレジスタで示されるバイト長の多数桁数値に対して、4ビット単位で右シ フトを行う命令です。よって、見方を変えればは数値が16で(BCD数値の 場合は10で)割られたのと同じことになります。また、最上位の4ビットの 内容は0になります。Zフラグのみが変化します。 書式 1111 1100 n :DSRL (n) サイクル数:4+Iサイクル f6:DSLL命令  DSLL(Decimal Shift to Left Loop ?)命令は、DSRLと同じように 内部RAMに存在するIレジスタで示されるバイト長の多数桁数値に対して、 4ビット単位で左シフトを行う命令です。よって、見方を変えればは数値が1 6倍(BCD数値の場合は10倍)されたのと同じことになります。また、最 下位の4ビットの内容は0になります。Zフラグのみが変化します。 書式 1110 1100 n :DSLL (n) サイクル数:4+Iサイクル g)比較命令  比較命令は、二つの数値の大小関係を調べたり、ある特定のビットの状態を 調べたりする命令のことです。 g1:CMP命令  CMP(COMpare)命令は、2つの数値の大小関係を調べる命令です。具体 的には、まず第1オペランドで指定された内容から、第2オペランドで指定さ れた内容を引きます。但し、その結果はどこにも残されずに、フラグの変化の みが利用されます。もし、第1オペランドの方が大きければ、Zフラグ、Cフ ラグとも0になります。また、第2オペランドの方が大きければCフラグが1 になります。そして、二つの数値が等しければZフラグが1になります。普通 CMP命令は8ビットですが、16ビット比較を行うCMPW命令や20ビッ ト比較を行うCMPP命令もあります。一般には、CMP命令と条件ジャンプ 命令を組み合わせることが多いです。 書式 0110 0000 n :CMP A,n (アキュムレータ即値) 0110 0001 m n :CMP (m),n (内部RAM即値) 0110 0010 m l k n :CMP [klm],n (外部メモリー即値) 0110 0011 n :CMP (n),A (内部RAMとアキュムレータ) 1011 0111 m n :CMP (m),(n) (内部RAM間) 1100 0110 m n :CMPW (m),(n) (16ビット内部RAM) 1101 0110 0000 0r2- m :CMPW (m),r2 (16ビットレジスタ) 1100 0111 m n :CMPP (m),(n) (20ビット内部RAM) 1101 0111 0000 0r3- m :CMPP (m),r3 (20ビットレジスタ) サイクル数 CMP A,n 3サイクル (アキュムレータ即値) CMP (m),n 4サイクル (内部RAM即値) CMP [klm],n 6サイクル (外部メモリー即値) CMP (n),A 4サイクル (内部RAMとアキュムレータ) CMP (m),(n) 6サイクル (内部RAM間) CMPW (m),(n) 8サイクル (16ビット内部RAM) CMPW (m),r2 7サイクル (16ビットレジスタ) CMPP (m),(n) 10サイクル (20ビット内部RAM) CMPP (m),r3 9サイクル (20ビットレジスタ) g2:TEST命令  TEST命令は、特定のビットの状態を調べるのに使います。具体的には、 第1オペランドの内容と第2オペランドの内容の論理積を取ります。CMP命 令と同じく結果はどこにも残らずに、フラグのみが変化を受けます。なお、T EST命令は8ビットのみです。 書式 0110 0100 n :TEST A,n (アキュムレータ即値) 0110 0101 m n :TEST (m),n (内部RAM即値) 0110 0110 m l k n :TEST [klm],n (外部メモリー即値) 0110 0111 n :TEST (n),A (内部RAMとアキュムレータ) サイクル数 TEST A,n 3サイクル (アキュムレータ即値) TEST (m),n 4サイクル (内部RAM即値) TEST [klm],n 6サイクル (外部メモリー即値) TEST (n),A 4サイクル (内部RAMとアキュムレータ) h)プログラム分岐命令  プログラム分岐命令は、プログラムの流れを変えるときに使う命令で、無条 件ジャンプ命令と、条件ジャンプ命令に分けられます。また、ジャンプの距離 によって、FARジャンプ、NEARジャンプ、SHORTジャンプに分けら れます。SHORTジャンプは、その性質から相対ジャンプと呼ばれます。 h1:JP(直接指定)、JPF命令 この命令は、条件に関わらずにプログラムの流れを変えるときに使われます。 さらに、ジャンプ先の絶対的なアドレスを記述するので絶対ジャンプと呼ばれ ます。JP(JumP)命令は、オペランドの内容をPCにとりこみます。PSレ ジスタは書き換えられないために、同じ64KBのページ内にしかジャンプす ることができません。JPF(JumP Far)命令は、PS、PCの両方を書き換 えるために1MBのメモリ空間のどこにへでもジャンプすることができます。 書式 0000 0010 n m :JP mn (NEARジャンプ) 0000 0011 n m l :JPF lmn (FARジャンプ) サイクル数 JP mn 4サイクル (NEARジャンプ) JPF lmn 5サイクル (FARジャンプ) h2:JP命令(間接指定)  このJP命令は、普通のJP命令とは異なり実質的にはJPF命令と同じ役 割をします。一般的にジャンプ命令のオペランドは即値ですがこの場合、20 ビットレジスタ、もしくは内部RAMにある20ビットポインタを指定するこ とができます。 書式 0001 0000 n :JP (n) (内部RAM指定) 0001 0001 0000 0r3- :JP r3 (レジスタ指定) サイクル数 JP (n) 6サイクル (内部RAM指定) JP r3 4サイクル (レジスタ指定) h3:JR命令  JRといっても鉄道とはなんの関係もありません。JRとは(Jump Relative)の略であり、その名が示すとおりジャンプ先のアドレスを相対的に 表します。具体的には、JR命令の次のアドレスにオペランドの数値を足した もの(JR−ならばオペランドの数値を引いたもの)がジャンプ先のアドレス となります。ただし、その際に16ビットのPCをオーバーフローもしくはア ンダーフローするときにも、PSは書き換えられません。つまり64KBのペー ジをまたぐような相対ジャンプはできないわけです。また、JR命令では±2 55バイトの範囲内でしかジャンプをすることができません。 書式 0001 001P :JR n サイクル数:3サイクル h4:JPcc命令  この命令は、フラグの状態によって、分岐したりしなかったりする命令です。 ccには、条件が入ります。条件が成り立っていれば、JP命令のようにオペ ランドで指定されたアドレスにジャンプします。条件が成り立っていなければ、 すぐ次の命令を実行します。 書式 0001 0100 n m :JPZ mn (Zフラグがセットされていればジャンプ) 0001 0101 n m :JPNZ mn (Zフラグがセットされていなければジャンプ) 0001 0110 n m :JPC mn (Cフラグがセットされていればジャンプ) 0001 0111 n m :JPNC mn (Cフラグがセットされていなければジャンプ) サイクル数 条件成立時(ジャンプするとき) :4サイクル 条件不成立(ジャンプしないとき):3サイクル h5:JRcc命令  この命令も、JPccと同じく条件によってプログラムの流れを分岐する命 令です。ただしアドレスは、JRのように相対的に指定します。 書式 0001 100P n :JRZ n (Zフラグがセットされていればジャンプ) 0001 101P n :JRNZ n (Zフラグがセットされていなければジャンプ) 0001 110P n :JRC n (Cフラグがセットされていればジャンプ) 0001 111P n :JRNC n (Cフラグがセットされていなければジャンプ) サイクル数 条件成立時(ジャンプするとき) :3サイクル 条件不成立(ジャンプしないとき):2サイクル i)サブルーチンコール命令 i1:CALL命令  CALL命令は、CALL命令のの次のアドレスをシステムスタックに保存 してから、指定されたアドレスをサブルーチンコールします。64KBのペー ジを越える場合には、CALLF命令を使います。 書式 0000 0100 n m :CALL mn (NEARコール) 0000 0101 n m l :CALLF lmn (FARコール) サイクル数 CALL mn 6サイクル (NEARコール) CALLF lmn 8サイクル (FARコール) i2:RET命令  CALL命令で、呼び出されたサブルーチンからメインルーチンに戻ります。 その際に、CALL命令でシステムスタックに保存されたアドレスを読みだし ます。読み出すバイト数の違いによって、RET(CALL命令で呼び出され た場合)RETF(CALLF命令で呼び出された場合)の二つがあります。 書式 0000 0110 :RET (NEARリターン) 0000 0111 :RETF (FARリターン) サイクル数 RET 4サイクル (NEARリターン) RETF 5サイクル (FARリターン) j)スタック操作命令  スタックとは、アドレスや数値を一時的に保存したりするときに使うもので す。この中には、CPUがCALLやRET命令を実行する際に自動的に使わ れるシステムスタックと、ユーザーが勝手に使うことのできるユーザースタッ クとがあります。システムスタックを操作するときには、戻り先の番地を消し てしまったりすることのないように注意する必要があります。 j1:PUSH命令  PUSH命令はスタックにレジスタの値をいれる命令です。システムスタッ クに関するPUSHS命令とユーザースタックに関するPUSHU命令があり ます。ただし、実はPUSH命令に相当するものはMV命令で表すことができ、 特にシステムスタック関係にはPUSHSという特別な命令は存在しません。 また、IMR(内部RAMアドレス&HFB)に対するPUSH命令ではIM Rをスタックにいれた後で、IMRのビット7を1にします。 書式 1011 0r1- 0011 0111 :PUSHS r1 (MV [--S],r1と同じです) 1011 0r2- 0011 0111 :PUSHS r2 (MV [--S],r2と同じです) 1011 0100 0011 0111 :PUSHS X  (MV [--S],Xと同じです) 1011 0101 0011 0111 :PUSHS Y  (MV [--S],Yと同じです) 0100 1111 :PUSHS F (フラグレジスタの内容) 0011 0000 1110 1000 0011 0111 1111 1011 :PUSHS IMR  (MV [--S],(0FBH)と同じです) 0010 1r1- :PUSHU r1 (8ビットレジスタ値をユーザースタックにいれる) 0010 1r2- :PUSHU r2 (16ビットレジスタ値をユーザースタックへ) 0010 1100 :PUSHU X (Xの内容をユーザースタックへ) 0010 1101 :PUSHU Y (Yの内容をユーザースタックへ) 0010 1110 :PUSHU F (フラグレジスタの内容をユーザースタックへ) 0010 1111 :PUSHU IMR (IMRの内容をスタックへ) サイクル数 PUSHS F 3サイクル(フラグレジスタの内容) PUSHU r1 3サイクル(8ビットレジスタ値をユーザースタックにいれる) PUSHU r2 4サイクル(16ビットレジスタ値をユーザースタックへ) PUSHU X 5サイクル(Xの内容をユーザースタックへ) PUSHU Y 5サイクル(Yの内容をユーザースタックへ) PUSHU F 3サイクル(フラグレジスタの内容をユーザースタックへ) PUSHU IMR 3サイクル(IMRの内容をスタックへ) j2:POP命令  POP命令はスタックからレジスタへ値をいれる命令です。システムスタッ クに関するPOPS命令とユーザースタックに関するPOPU命令があります。 ただし、PUSHと同じくPOP命令に相当するものもMV命令で表すことが でき、特にシステムスタック関係にはPOPSという特別な命令は存在しませ ん。 書式 1001 0r1- 0011 0111 :POPS r1 (MV r1,[S++]と同じです) 1001 0r2- 0011 0111 :POPS r2 (MV r2,[S++]と同じです) 1001 0100 0011 0111 :POPS X  (MV X,[S++]と同じです) 1001 0101 0011 0111 :POPS Y  (MV Y,[S++]と同じです) 0101 1111 :POPS F (フラグレジスタの内容) 0011 0000 1110 0000 0010 0111 1111 1011 :POPS IMR  (MV (0FBH),[S++]と同じです) 0011 1r1- :POPU r1 (ユーザースタックから8ビットレジスタ) 0011 1r2- :POPU r2 (ユーザースタックから16ビットレジスタへ) 0011 1100 :POPU X (ユーザースタックからXへ) 0011 1101 :POPU Y (ユーザースタックからYへ) 0011 1110 :POPU F (ユーザースタックからフラグレジスタへ) 0011 1111 :POPU IMR (ユーザースタックからIMRへ) サイクル数 POPS F 2サイクル(フラグレジスタの内容) POPU A 2サイクル(ユーザースタックからAレジスタ) POPU IL 3サイクル(ユーザースタックからIL・実質16ビット) POPU r2 3サイクル(ユーザースタックから16ビットレジスタへ) POPU X 4サイクル(ユーザースタックからXへ) POPU Y 4サイクル(ユーザースタックからYへ) POPU F 2サイクル(ユーザースタックからフラグレジスタへ) POPU IMR 2サイクル(ユーザースタックからIMRへ) k)その他の命令 k1:NOP命令  NOP(No OPeration)とはその名の通り何もしない命令です。デバッグ時 の埋め合せや時間稼ぎに使います。 0000 0000 :NOP サイクル数:1サイクル k2:WAIT命令  Iレジスタで指定された時間、何もしません。 1110 1111 :WAIT サイクル数:1+Iサイクル k3:SC、RC命令  キャリーフラグの状態を決める命令です。SC命令はキャリーフラグをセッ トし、RC命令はキャリーフラグをリセットします。この命令はキャリーフラ グが関係する演算命令の前に使ったり、キャリーフラグを値に返すサブルーチ ン(例えば正常に動作したらキャリーフラグをリセットして、異常が起きたら セットする。)などに良く使われます。 1001 0111 :SC 1001 1111 :RC サイクル数  どちらも1サイクル k4:RETI命令  割り込み処理ルーチンから復帰します。割り込みがかかったときには、アド レス3バイトと、フラグレジスタ、IMRが保存されています。 0000 0001 :RETI サイクル数:7サイクル k5:HALT、OFF命令  CPUの動作を停止します。復帰させるにはリセットをかけるか、割り込み をかけなければなりません。 1101 1110 :HALT 1101 1111 :OFF サイクル数:2サイクル k6:TCL、IR、RESET命令  何をする命令か良くわかりません。 1100 1110 :TCL 1111 1110 :IR 1111 1111 :RESET サイクル数は不明です 第4章 マシン語を使おう  前の章ではマシン語の命令一つ一つについて解説しました。この章では、実 際にマシン語の簡単なプログラムを動かしてみて、マシン語のプログラムはど のようなものなのか、またどの様なことができるのかをみていきます。 4.1 始める前に  PC−E500シリーズでは、勝手な場所にマシン語のプログラムを置くこ とができません。これは、メモリー全てがBASICによって管理されている からです。もし、勝手な位置にプログラムをおいてしまうと、マシン語のプロ グラムがBASICによって消されてしまったり、最悪の場合にはオールリセッ トするしかなくなることもあります。そのために、あらかじめマシン語のプロ グラムを置く場所をBASICの管理からはずしておく必要があります。この 章のプログラムでは&HBFB00から&HBFBFFまでの256バイトを マシン語領域とします。次のようにして、このマシン語領域を確保します。 POKE &HBFE03,&H1A,&HFD,&H0B,&H00,&H01,&H00 CALL &HFFFD8  これで、&HBFB00から&HBFBFFまでが、マシン語領域として確 保されました。この後のプログラムを実行する前に必ずこの操作をして下さい。 4.2 足し算・引き算  マシン語で最初のプログラムは何がよいでしょうか。ある本には初めての言 語で作る最初のプログラムは、画面に”Hello,world”と表示させ るのがよいと書いてありましたが、マシン語の場合これは非常に困難です。そ こでとりあえず、なるべく簡単な命令だけを使って進めていくことにします。 わからない命令があったら第3章の命令の解説のところを読み返して下さい。  それでは、まずはマシン語による足し算をやってみることとします。それで は、次のプログラムを打ち込んでみましょう。 アドレス コード ニモニック BFB00 88 80 FB 0B START:MV A,[0BFB80H] ;&HBFB80の内容と BFB04 89 81 FB 0B MV IL,[0BFB84H] ;&HBFB84の内容を BFB08 46 01 ADD A,IL ;足して BFB0A A8 82 FB 0B MV [0BFB88H],A ;&HBFB88にいれる BFB0E 9F RC BFB0F 07 RETF ;BASICに戻る  後ろにコメントを入れておきました。このプログラムは、&HBFB80と &HBFB84の内容を足して、&HBFB88に書き込むものです。最後の RETFは、BASICに戻るためのもので、これがないと暴走します。  一般に、マシン語のプログラムは人間の理解することのできるニモニックと いうものを用いて書き、これをなんらかの方法でコードに変換して行きます。 このことをアセンブルすると言い、また人間がアセンブルすることをハンドア センブル、コンピュータによって、アセンブルするためのプログラムをアセン ブラといいます。この場合は、すでにマシン語に変換してありますので、皆さ んはとくに気にする必要はありません。  あっと、そういえばマシン語のプログラムを書き込む方法を言ってませんで した。普通、マシン語のプログラムはモニタと呼ばれるプログラムを使って打 ち込むのですが、これはそんなに大げさなプログラムではないので、ここでは BASICのプログラムを使って打ち込んでみます。 10:POKE &HBFB00,&H88,&H80,&HFB,&H0B,&H89,&H84,&HFB,&H0B,&H46 ,&H01,&HA8,&H88,&HFB,&H0B,&H9F,&H07 20:INPUT A:POKE &HBFB80,A 30:INPUT B:POKE &HBFB84,B 40:CALL &HBFB00 50:PRINT PEEK &HBFB88 60:GOTO 20  10行で、マシン語を書き込んで、20から60行までで実行を行います。 ちゃんと足し算しているでしょう。だたし計算結果が255を越えた場合は下 位1バイト分のみが表示されます。これは8ビットレジスタを使用しているた めです。次のようにすれば20ビットまでの計算ができるようになります。 BFB00 8C 80 FB 0B START:MV X,[0BFB80H] ;&HBFB80からの内容と BFB04 8D 81 FB 0B MV Y,[0BFB84H] ;&HBFB84からの内容を BFB08 45 45 ADD X,Y ;足して BFB0A AC 82 FB 0B MV [0BFB88H],X ;&HBFB88からにいれる BFB0E 9F RC BFB0F 07 RETF ;BASICに戻る 10:POKE &HBFB00,&H8C,&H80,&HFB,&H0B,&H8D,&H84,&HFB,&H0B,&H45 ,&H45,&HAC,&H88,&HFB,&H0B,&H9F,&H07 20:INPUT A:A$=RIGHT$ ("0000"+HEX$ (A)):POKE &HBFB80,VAL ("&H" +RIGHT $(A$,2)),VAL ("&H"+MID$ (A$,2,2)),VAL ("&H"+LEFT$ (A$,1)) 30:INPUT B:B$=RIGHT$ ("0000"+HEX$ (B)):POKE &HBFB84,VAL ("&H" +RIGHT$ (B$,2)),VAL ("&H"+MID$ (B$,2,2)),VAL ("&H"+LEFT$ (B$,1)) 40:CALL &HBFB00 50:PRINT PEEK &HBFB88+PEEK &HBFB89*256+PEEK &HBFB8A*65536 60:GOTO 20 ところでINPUTで入力された値をわざわざHEX$命令を使って、いっ たん文字列にしてから各バイト毎に分割するのは、私のPC−E500にはI NT命令のバグがあるためにINT命令で分割することができないためです。  さて、引き算も全く同じようにすることができます。最初のプログラムの& HBFB08番他を BFB08 4E 01 SUB A,IL また後のプログラムでも BFB08 4D 45 SUB X,Y  にすれば引き算をするプログラムになります。 4.3 多数桁の足し算・引き算  さて今度はもっと大きな数の計算をしてみましょう。前節のプログラムでは 1つのレジスタに入れることの数までしか計算できませんでした。それより大 きな数の計算をするにはいわゆる筆算の方法を使います。 BFB00 0C 80 FB 0B START:MV X,0BFB80H ;データのあるアドレスをセット BFB04 05 10 MV IL,10H ;データの長さ(16バイト) BFB06 9F RC ;最初の計算は繰り上がりがない BFB07 90 04 LOOP :MV A,[X] ;データをロード BFB09 E0 84 01 10 MV (BP+1),[X+10H] BFB0D 52 01 ADC A,(BP+1) ;繰り上がりを含んだ足し算 BFB0F B0 C4 20 MV [X+20H],A ;答えをストア BFB12 6C 04 INC X ;次のデータへ BFB14 7C 01 DEC IL ;16バイト計算したら BFB16 1B 11 JRNZ LOOP BFB18 9F RC BFB19 07 RETF ;BASICへもどる 次のように変更すると引き算のプログラムになります BFB0D 5A 01 SBC A,(BP+1) このプログラムは&HBFB80から16バイトと&HBFB90から16 バイトを足して&HBFBA0から16バイトに格納します。(BASICは 省略させていただきます、なんせBASICの有効数字の範囲を越えています ので。)プログラムの内容は、1バイトづつの計算を繰り返しているだけです。 このような場合のためにキャリーを含めた演算命令であるADC/SBC命令 があるのです。キャリー・フラグというのは計算結果がオーバーフロー/アン ダーフローしたときに発生します。これは普通の計算における繰上げ/繰下げ に対応します。(決して繰上げしなければならない値は2以上にはならないこ とに注意。)したがって、次の桁を計算するときに繰上げした分だけ余分に足 せば良いわけです。  ここで鋭い人なら次のことに気付いたはずです。このプログラムではADC を実行した後にINCやDECなどの命令がありますが、これらの命令によっ て繰り上がりの情報を示すキャリー・フラグが変化を受けることはないのでしょ うか。結論からいいますとその様なことの起きないようになっています。IN CやDECではキャリー・フラグを変化させることはできません。もし変化を 受けるとしたらループの回数を指定する方法がなくなってしまうからです。 4.4 かけ算・割り算  さて、マシン語の命令表をみてもらえばわかるようにSC62015には足 し算、引き算の命令はあってもかけ算、割り算の命令はありません。そこで、 ここではマシン語でかけ算、割り算をする方法を考えてみましょう。まずはか け算からですが、普通に考える一番簡単な方法は、一つの数をもう一つの数の 回数だけ足すことでしょう。これをプログラムにすると次のようになります。 BFB00 D0 01 80 FB 0B START:MV (BP+1),[0BFB80H] ;掛けられる数 BFB05 89 84 FB 0B MV I,[0BFB84H] ;掛ける数(回数) BFB09 08 00 MV A,0 ;答えのはいる場所 BFB0B 42 01 LOOP :ADD A,(BP+1) ; 掛ける数の回数 BFB0D 7C 01 DEC IL ; だけ掛ける数を BFB0F 1B 06 JRNZ LOOP ; 足す BFB11 A8 88 FB 0B MV [0BFB88H],A ;答えを&HBFB88に入れる BFB15 9F RC BFB16 07 RETF ;BASICに戻る  これを実行させるためには次のBASICを打ち込みます。 10:POKE &HBFB00,&HD0,&H01,&H80,&HFB,&H0B,&H89,&H84,&HFB,&H0B ,&H08,&H00,&H42,&H01,&H7C,&H01,&H1B,&H06,&HA8,&H88,&HFB ,&H0B,&H9F,&H07 20:INPUT A:POKE &HBFB80,A 30:INPUT B:POKE &HBFB84,B 40:CALL &HBFB00 50:PRINT PEEK &HBFB88 60:GOTO 20 このプログラムで8ビットのかけ算をすることができましたが、1×255 を計算するときには、ループを255回もまわります。これが、16ビットの 計算になると、65535回もまわる可能性が出できます。これでは遅すぎて 実用になりません。そこで、ほかの方法をかんがえてみます。皆さん自身が、 大きな数どうしのかけ算をする場合どうしていますか。(電卓を使うというの は反則!)そうです、筆算をするのです。この筆算のアルゴリズムをマシン語 化すると次のようになります。 BFB00 D0 01 80 FB 0B START:MV (BP+1),[0BFB80H] ;掛けられる数 BFB05 D0 02 84 FB 0B MV (BP+2),[0BFB84H] ;掛ける数 BFB0A 08 00 MV A,0 ;答えを入れる場所 BFB0C 09 08 MV IL,8 ;ループ回数(8ビット) BFB0E F5 01 NEXT :SHR (BP+1) ;もし、掛ける数の BFB10 1E 02 JRNC SKIP ;nビット目が1ならば BFB12 42 02 ADD A,(BP+2) ; 掛けられる数を足す BFB14 9F SKIP :RC BFB15 F7 02 SHL (BP+2) ;掛けられる数を2倍 BFB17 7C 01 DEC IL BFB19 1B 0D JRNZ NEXT ;8ビット繰り返し BFB1B A8 88 FB 0B MV [0BFB88H],A ;答えを入れる BFB1F 9F RC BFB20 07 RETF ;BASICに戻る  これを、BASICの命令を使って書き込みます。 10:POKE &HBFB00,&HD0,&H01,&H80,&HFB,&H0B,&HD0,&H02,&H84,&HFB ,&H0B,&H08,&H00,&H09,&H08,&HF5,&H01 11:POKE &HBFB10,&H1E,&H02,&H42,&H02,&H9F,&HF7,&H02,&H7C,&H01 ,&H1B,&H0D,&HA8,&H88,&HFB,&H0B,&H9F,&H07 実行方法はいままでどうりです。2進数の筆算ですから、2倍するためのS HL命令と足し算命令のADDを使うだけで計算できます。このアルゴリズム の場合、ループの回数は8ビットで8回、16ビットで16回というように大 幅に減少します。  次に割り算をしてみましょう。割り算というのは、基本的に引き算として実 行することができます。つまり、AをBで割るときには、Aから何回Bが引け るかを数えれば良いのです。ちなみに、このときAに残った数が余りになりま す。それでは、これをマシン語にしてみましょう。 BFB00 D0 01 80 FB 0B START:MV (BP+1),[0BFB80H] ;割られる数 BFB05 88 84 FB 0B MV A,[0BFB84H] ;割る数 BFB09 60 00 CMP A,0 ;割る数=0ならば BFB0B 18 17 JRZ ERROR ;エラー BFB0D 09 00 MV IL,0 ;答え=0 BFB0F 63 01 NEXT :CMP (BP+1),A ;割られる数から BFB11 1C 06 JRC EXIT ;割る数が引ければ BFB13 4B 01 SUB (BP+1),A ; 引いて BFB15 6C 01 INC IL ; 答えに1を加えて BFB17 13 0A JR NEXT ; 繰り返し BFB19 9F EXIT :RC ;引けなければ BFB1A A9 88 FB 0B MV [0BFB88H],IL ; 答えと BFB1E D8 8C FB 0B 01 MV [0BFB8CH],(BP+1) ; 余りを入れて BFB23 07 RETF ; BASICに戻る BFB24 97 ERROR:SC ;エラー21 BFB25 08 15 MV A,15H ;Division by zero BFB27 07 RETF ;が出るようにセット  こんどは、割り算の商だけでなく余りも返すようにしたので、プログラム全 体を書き換えます。 10:POKE &HBFB00,&HD0,&H01,&H80,&HFB,&H0B,&H88,&H84,&HFB,&H0B ,&H60,&H00,&H18,&H17,&H09,&H00,&H63 20:POKE &HBFB10,&H01,&H1C,&H06,&H4B,&H01,&H6C,&H01,&H13,&H0A ,&H9F,&HA9,&H88,&HFB,&H0B,&HD8,&H8C 30:POKE &HBFB20,&HFB,&H0B,&H01,&H07,&H97,&H08,&H15,&H07 40:INPUT A:POKE &HBFB80,A 50:INPUT B:POKE &HBFB84,B 60:CALL &HBFB00 70:PRINT PEEK &HBFB88,PEEK &HBFB8C 80:GOTO 40  ところで、間違って0で割り算をしてしまったときはどうなるのでしょうか。 このアルゴリズムでは、永久ループにはいってしまいます。そのため、プログ ラムの最初で割る数をチェックして、0であればエラーを発生するようにして あります。 4.5 マシン語でエラーを出そう  前節の終わりのところでも出てきましたが、マシン語からBASICのエラー を発生させるにはどうすればよいのでしょうか。これは実に簡単で、BASI Cに戻るときにキャリーフラグをセットしておけば良いのです。今までのプロ グラムで、RC命令が使われていたのは、オーバーフローしたときにエラーが 出てストップすることのないようにするためです。Aレジスタにエラーコード を代入しておけば、希望するエラーを発生させることができます。先ほどのプ ログラムでは、エラーコード21のDivision By Zeroが使われています。 BFB00 97 SC ;エラーを発生するようにキャリーフラグをセット BFB01 08 0A MV A,0AH ;エラーコード10:Syntax error BFB03 07 RETF ;BASICに戻る  なお、存在しないエラーコードを指定するとただErrorと表示するだけです。 4.6 キー入力  マシン語でキー入力するにはどうしたら良いのでしょうか、最も簡単な方法 はROMの中にあるキー入力ルーチンを呼び出すことです。まずは、BASI CのINPUT$に相当するサブルーチンを使うことにしましょう。 BFB00 30 CD D6 01 00 START:MVW (0D6H),1 BFB05 0B 43 00 MV I,43H BFB08 08 00 MV A,0 BFB0A 05 E8 FF 0F CALLF 0FFFE8H BFB0E AA 80 FB 0B MV [0BFB80],BA BFB12 07 RETF  このプログラムをいままでどうりBASICから書き込んでみましょう。 10:POKE &HBFB00,&H30,&HCD,&HD6,&H01,&H00,&H0B,&H43,&H00,&H08 ,&H00,&H05,&HE8,&FF,&H0F,&HAA,&H80,&HFB,&H0B,&H07 20:CALL &HBFB00 30:PRINT CHR$ PEEK &HBFB80;:GOTO 20  このプログラムは、現在押されているキーのコードをINPUT$と同じ形 で返します。よって、CHR$関数を使えば現在押されているキーに相当する キャラクタが表示されるはずです。このサブルーチンは、内部RAMのD6H、 D7Hにそれぞれ1と0、また、Iレジスタに43Hをセットして、FFFE 8Hを呼び出すことで実行されます。  ところで、このプログラムには重大な欠点があります。それは、キーを押しっ ぱなしにしていることが検出できないのです。それでは、次にINKEY$に 相当するサブルーチンを使ってみましょう。 BFB00 30 CD D6 01 00 START:MVW (0D6H),1 BFB05 0B 42 00 MV I,42H BFB08 08 00 MV A,0 BFB0A 05 E8 FF 0F CALLF 0FFFE8H BFB0E AA 80 FB 0B MV [0BFB80],BA BFB12 0B 45 00 MV I,45H BFB15 05 E8 FF 0F CALLF 0FFFE8H BFB19 07 RETF 10:POKE &HBFB00,&H30,&HCD,&HD6,&H01,&H00,&H0B,&H42,&H00,&H08 ,&H00,&H05,&HE8,&FF,&H0F,&HAA,&H80 20:POKE &HBFB10,&HFB,&H0B,&H0B,&H45,&H00,&H05,&HE8,&HFF,&H0F ,&H07 30:CALL &HBFB00 40:PRINT PEEK &HBFB80;PEEK &BFB81;:GOTO 20  どうでしょう。2つづつ数字が表示されます。一つ目の数字は、どのキーが 押されたか、または離されたかを表す数字で次のような意味を持っています。 +---+-------+-------+-------+-------+-------+-------+-------+ | | 00 | 10 | 20 | 30 | 40 | 50 | 60 | +---+-------+-------+-------+-------+-------+-------+-------+ | 0| | | 0 | SPACE | P | hyp | RCL | | 1| SHIFT | | 1 | A | Q | sin | STO | | 2| CTRL | INS | 2 | B | R | cos | | | 3| ON | PF-1 | 3 | C | S | tan | | | 4| OFF | PF-2 | 4 | D | T | FSE | | | 5| BASIC | PF-3 | 5 | E | U | HEX | | | 6| MENU | PF-4 | 6 | F | V | DEG | | | 7| カナ | PF-5 | 7 | G | W | ln | | | 8| BS | | 8 | H | X | log | | | 9| CAPS | | 9 | I | Y | 1/x | | | A| 2ndF | | * | J | Z | *2 | | | B| DEL | | + | K | = | EXP | | | C| C・CE | → | , | L | ; | yX | | | D| REUTRN| ← | − | M | ( | √ | | | E| *1 | ↑ | . | N | ) | x2 | | | F| A-POFF| ↓ | / | O | | +/- | | +---+-------+-------+-------+-------+-------+-------+-------+ *1 は上下三角キー(左上角) *2 は上下矢印キー(右上)  それぞれのキーを押したときには、この表にあるとおりの(当然10進数で 表示されているが)数が表示されます。また離したときには、この表にある数 +128が表示されるはずです。また、2つめの数字はキーの状態が変わった かどうかを表し、0であればそのまま1であれば何か変化が起きたことを表し ます。 4.7 同時キー入力  さて、このサブルーチンをうまく使えばゲームなどにも応用できそうですが、 ゲームの場合にはもう一つ問題が出てきます。それは3つ以上のキーの状態を 調べることができないことです。(2つまではROM内サブルーチンでサポー トしています)例えば、シューティングゲーム(ただ単純に敵を撃ちまくるゲー ム。他人にやらせるとキーが痛むので注意!)を作ったとして、味方を動かし ながら、弾を発射させたいときにはどうすれば良いのでしょうか。このような ときに使われるのが同時キー入力です。とにかく次のプログラムを実行させて 下さい。 BFB00 30 CD F0 01 00 START:MVW (0F0H),01H BFB05 30 D8 80 FB 0B F2 MV [0BFB80],(0F2H) BFB0B 07 RETF 10:POKE &BFB00,&H30,&HCD,&HF0,&H01,&H00,&H30,&HD8,&H80,&HFB ,&H0B,&HF2,&H07 20:CALL &BFB00:PRINT PEEK &HBFB80;:GOTO 20  このプログラムは、一番左の方のキーについて同時キー入力します。この後 にある表をみてもらえばわかるようにQは2、Aは8に対応しています。よっ て、この2つのキーを同時に押せば10と表示されるはずです。これだけのキー についてだけやっていても面白くないので、全てのキーについて同時キー入力 をやってみましょう。 BFB00 0C 80 FB 0B START:MV X,0BFB80H BFB04 09 0C MV IL,0CH BFB06 30 CD F0 01 00 MVW (0F0H),01H BFB0B 30 E8 24 F2 NEXT :MV [X++],(0F2H) BFB0F 9F RC BFB10 30 F7 F0 SHL (0F0H) BFB13 30 F7 F1 SHL (0F1H) BFB16 7C 01 DEC IL BFB18 1B 0F JRNZ NEXT BFB1A 07 RETF 10:POKE &HBFB00,&H0C,&H80,&HFB,&H0B,&H09,&H0C,&H30,&HCD,&HF0 ,&H01,&H00,&H30,&HE8,&H24,&HF2,&H9F 20:POKE &HBFB10,&H30,&HF7,&HF0,&H30,&HF7,&HF1,&H7C,&H01,&H1B ,&H0F,&H07 30:CALL &BFB00 40:FOR I=0 TO 11:PRINT PEEK (&HBFB80+I);:NEXT I:PRINT :GOTO 30 どうです、すごいでしょう(単なる自己満足)。キーと数字の対応は次のよう になっています。 スキャンライン(F0H) (F1H)は0 +---+-----+-----+-----+-----+-----+-----+-----+-----+ | | 01| 02| 04| 08| 10| 20| 40| 80| +---+-----+-----+-----+-----+-----+-----+-----+-----+ | 01| *1 | W | R | Y | I | RCL | STO | C・CE| | 02| Q | E | T | U | O | hyp | sin | cos | | 04| MENU| S | F | H | K | HEX | DEG | ln | | 08| A | D | G | J | L | EXP | yX | √ | | 10| BASI| X | V | N | , | 7 | 8 | 9 | | 20| Z | C | B | M | ; | 4 | 5 | 6 | | 40| SHFT| CAPS| SPC | ↑ | → | 1 | 2 | 3 | | 80| CTRL| カナ| ↓ | ← | RTN | 0 | +/- | . | +---+-----+-----+-----+-----+-----+-----+-----+-----+ スキャンライン(F1H) (F0H)は0 +---+-----+-----+-----+-----+ | | 01| 02| 04| 08| +---+-----+-----+-----+-----+ | 01| *2 | ) | P | OFF | | 02| tan | FSE | 2ndF| ----| | 04| log | 1/X | PF5 | ----| | 08| X2 | ( | PF4 | ----| | 10| ÷/| DEL | PF3 | ----| | 20| ×*| BS | PF2 | ----| | 40| − | INS | PF1 | ----| | 80| + | = | ----| ----| +---+-----+-----+-----+-----+ *1 は上下三角キー(左上角) *2 は上下矢印キー(右上)  実は(F0H)と(F1H)に、読みだしたいキーの列を書き込んで、(F 2H)をよみだすと、その列のキーの状態がわかるようになっているのです。 但し、(F1H)のほうは、キーだけでなくSIOも使用するので、8より大 きな数を書き込まないで下さい。ちなみに(F0H)と(F1H)にはキーポー ト・アウトプット・バッファ、(F2H)にはキーポート・インプット・バッ ファという名前がつけられています。(マシン語の解説参照)  さて、ここまでキー入力についてみてきたわけですが、一つだけ今までの方 法では入力できないキーがあります。それは、ONキーです。これはONキー がブレーク・キーの役割のほかに電源スイッチの役割をしているためです。と ころが、ワークエリア内に、ONキーが押されているかどうかを示す場所があ るのです。それは、&HBFCBEのビット7です。その証拠に次のように操 作してみて下さい。 FOR I=0 TO 100:POKE &HBFCBE,128:NEXT I  すぐにBreakと表示されたでしょう。ちなみに、ここのビット6はLo w Batteryを示すフラグになっています。さて、ONキーの読みだし 方はわかりましたが、プログラムを中断せずにONキーの状態を調べることは できないでしょうか。普通、ONキーを押すと、その時点でプログラムが中断 されてしまいます。そんなときは、&HEAに0を書き込めば良いのです。こ れで、ONキーを押してもプログラムは決して止まりません。(ほとんどPC −1600のBREAK OFF命令みたいだなぁ)元に戻すときは、8を書 き込んで下さい。 4.8 画面表示  さて、キー入力の次は画面表示をやってみましょう。まずは、1文字出力です。 BFB00 30 CD D6 00 00 START:MVW (0D6H),0 BFB05 0B 41 00 MV I,41H BFB08 08 41 MV A,41H BFB0A 05 E8 FF 0F CALLF 0FFFE8H BFB0E 07 RETF POKE &HBFB00,&H30,&HCD,&HD6,&H00,&H00,&H0B,&H41,&H00,&H08,&H41 ,&H05,&HE8,&HFF,&H0F,&H07 CALL &HBFB00  うーん、困りました。プログラムにして表示させようと思ったのですが、ど うもうまく行きません。実は、このプログラムの前に表示位置を設定しなけれ ばなりません。(D4H:X座標、D5H:Y座標)どうもこれもマシン語で やらなければならないようです。(面倒なのでやめ!)さて、CALL文を実 行してどうなったかわかりますか、CALLがAALLになっているでしょう。 座標の設定をしなかったために、キー入力をした行の左端に表示されています。 4.9 インジケータを操ろうU  さて、次は第2章でもやったインジケータを操作してみたいと思います。今 度はワークエリアをいじくるのではなく、画面を操作するサブルーチンを呼び 出します。それでは、次のプログラムをいれて下さい。 BFB00 30 CD D6 00 00 START:MVW (0D6H),0 BFB05 0B 46 00 MV I,46H BFB08 30 CC D4 00 MV (0D4H),0 BFB0C 08 01 MV A,01H BFB0E 05 E8 FF 0F CALLF 0FFFE8H BFB12 07 RETF POKE &HBFB00,&H30,&HCD,&HD6,&H00,&H00,&H0B,&H46,&H00,&H30,&HCC ,&HD4,&H00,&H08,&H01,&H05,&HE8,&HFF,&H0F,&H07 CALL &BFB00  BATTがついたと思います。どこのシンボルをつけるかどうかは、次の表 のようになっています。 +---+-------+-------+-------+-------+-------+ | | 01 | 02 | 04 | 08 | 10 | +---+-------+-------+-------+-------+-------+ | 0| BATT | | | | | | 1| BUSY | RUN | PRO | DBL | | | 2| 小文字| カナ | HYP | CAPS | 2ndF | | 3| PRINT | E | RAD | G | DE | +---+-------+-------+-------+-------+-------+  この表の左側の数字を(D4H)にいれて、上の数字をAレジスタにいれる ことによって指定します。さっきの例では、D4H=0、A=1となっていま すからBATTがつくわけです。 4.10 スクロール  さて、次はスクロールをしてみましょう。スクロールというのは例えばBA SICを使っていて、画面の一番下のところで改行すると画面全体が1行づつ 上に上がるというやつです。(ちなみにスクロールには巻物という意味があり ます。)マシン語では、このようなスクロールアップのほかにスクロールダウ ンをすることもできます。 スクロール・アップ BFB00 30 CD D6 00 00 START:MVW (0D6H),0 BFB05 0B 47 00 MV I,47H BFB08 30 CD D4 00 00 MVW (0D4H),0 BFB0D 30 CD D8 27 03 MVW (0D8H),0327H BFB12 08 01 MV A,01H BFB14 05 E8 FF 0F CALLF 0FFFE8H BFB18 07 RETF スクロール・ダウン BFB20 30 CD D6 00 00 START:MVW (0D6H),0 BFB25 0B 48 00 MV I,48H BFB28 30 CD D4 00 00 MVW (0D4H),0 BFB2D 30 CD D8 27 03 MVW (0D8H),0327H BFB32 08 01 MV A,01H BFB34 05 E8 FF 0F CALLF 0FFFE8H BFB38 07 RETF 10:POKE &HBFB00,&H30,&HCD,&HD6,&H00,&H00,&H0B,&H47,&H00,&H30 ,&HCD,&HD4,&H00,&H00,&H30,&HCD,&HD8,&H27,&H03,&H08,&H01 ,&H05,&HE8,&HFF,&H0F,&H07 20:POKE &HBFB20,&H30,&HCD,&HD6,&H00,&H00,&H0B,&H48,&H00,&H30 ,&HCD,&HD4,&H00,&H00,&H30,&HCD,&HD8,&H27,&H03,&H08,&H01 ,&H05,&HE8,&HFF,&H0F,&H07 30:LINE(0,0)-(239,31):FOR I=0 TO 3:CALL &HBFB00:FOR J=0 TO 1000 :NEXT:NEXT 40:LINE(0,0)-(239,31):FOR I=0 TO 3:CALL &HBFB20:FOR J=0 TO 1000 :NEXT:NEXT  &HBFB00からが普通のスクロール、&HBFB20からが逆のスクロー ルになっています。なお、BASICのプログラムでは、どうなっているかを 確かめるためにウエイトをいれてあります。 4.11 画面反転  さて、次は画面の反転をやりたいのですが困ったことに、これにはROM内 サブルーチンはサポートしていないようです。(私の解析不足かも知れません が)そのために、画面を直接コントロールすることにします。PC−E500 シリーズでは、画面の制御用にLCDC(LCD Controller)と呼ばれるLSI を使っています。画面は、このLCDCを通してしか操作することができませ ん。LCDCの置かれているアドレスは次のようになっています。 LCDC1:0A004H−0A007H LCDC2:0A008H−0A00BH  また、LCDC1/2の同時アクセスも可能で、この場合のアドレスは0A 000−0A003Hになります。なお、アドレスの下位2ビットはコマンド によって違っています。LCDCに対するコマンドは次の通りです。それぞれ のコマンドはアドレス、またはアドレスと出力データ1バイトで指定します。 1.表示ON  LCD画面の表示をONにします。V−RAMのデータは変化しません。 アドレス下位2ビット:00 出力データ :3FH 2.表示OFF  LCD画面の表示をOFFにします。V−RAMのデータは変化しません。 アドレス下位2ビット:00 出力データ :3EH 3.表示開始ラインセット  LCDの最上段に表示されるV−RAMのラインをセットします。 アドレス下位2ビット:00 出力データ :C0H+表示開始ライン(0〜3FH) 4.ページ(Xアドレス)のセット  表示位置を指定するためのページ(Xアドレス)をセットします。 アドレス下位2ビット:00 出力データ :B8H+Xアドレス(0〜7) 5.Yアドレスのセット  表示位置を指定するためのYアドレスをセットします。 アドレス下位2ビット:00 出力データ :40H+Yアドレス(0〜3FH) 6.スティタス・リード  LCDCの状態を読みだします。それぞれの意味は次のようになっています。 RESET (ビット4) 1:リセット  0:ノーマル ON/OFF(ビット5) 1:表示OFF 0:表示ON BUSY  (ビット7) 1:内部動作中 0:READY状態 アドレス下位2ビット:01 7.表示データ書き込み  データをV−RAMに書き込みます。書き込み後Yアドレスを+1します。 アドレス下位2ビット:10 出力データ :書き込みデータ 8.表示データ読みだし  データをV−RAMから読みだします。読みだし後Yアドレスを+1します。 アドレス下位2ビット:11  また画面の割当は表示開始ラインが0の場合次の様になっています。という のは、表示開始ラインによって画面の位置が変わって来るからです。図中では LCDC1は[1]、LCDC2は[2]で表してあります。また、インジケー タのX、Yアドレスの割り当ても示します。インジケータのアドレスはLCD C2のものとなります。        Yアドレス 0------>63 0----->55 55<-----0 63<-----0 0 63 64 119 120 175 176 239 ……… X座標 0+---------+---------+---------+---------+ | [1] X=0 | [2] X=0 | [2] X=4 | [1] X=4 | 8+---------+---------+---------+---------+ | [1] X=1 | [2] X=1 | [2] X=5 | [1] X=5 | 16+---------+---------+---------+---------+ | [1] X=2 | [2] X=2 | [2] X=6 | [1] X=6 | 24+---------+---------+---------+---------+ | [1] X=3 | [2] X=3 | [2] X=7 | [1] X=7 | +---------+---------+---------+---------+ Y座標  インジケータ +---+---+-------+-------+-------+-------+-------+ | X| Y| 4 | 3 | 2 | 1 | 0 | +---+---+-------+-------+-------+-------+-------+ | 0 | 63| | DBL | PRO | RUN | BUSY | | 4 | 63| 2ndF | CAPS | HYP | カナ | 小文字| | 5 | 63| DE | G | RAD | E | PRINT | | 6 | 63| | | | | BATT | +---+---+-------+-------+-------+-------+-------+  但し、直接画面を操作するときでも、カーソルはタイマ割り込みで自動的に 点滅するので、これらとのかち合いを防ぐため割り込みを禁止(2FHを実行 する)しなければなりません。アクセスが終わったら3FHを実行して元の状 態に戻す必要があります。  それでは、さっそくプログラムを作ってみましょう BFB00 2F START: PUSHU IMR ;割り込みを禁止 BFB01 30 CC FB A0 MV IMR,0A0H BFB05 CC 01 B8 MV (BP+01),0B8H ;Xアドレスの初期値 BFB08 D8 04 A0 00 01 NEXTX: MV [0A004H],(BP+01) ;Xアドレスをセット BFB0D CC 02 40 MV (BP+02),40H ;Yアドレスの初期値 BFB10 D8 04 A0 00 02 NEXTY1:MV [0A004H],(BP+02) ;Yアドレスをセット BFB15 04 77 FB CALL LOOP ;タイミングをとる BFB18 88 07 A0 00 MV A,[0A007H] ;空読み BFB1C 04 77 FB CALL LOOP BFB1F 88 07 A0 00 MV A,[0A007H] ;データを読み込む BFB23 04 77 FB CALL LOOP BFB26 D8 04 A0 00 02 MV [0A004H],(BP+02) ;Yアドレスをセット BFB2B 68 FF XOR A,0FFH ;データを反転して BFB2D 04 77 FB CALL LOOP BFB30 A8 06 A0 00 MV [0A006H],A ;画面に書き込む BFB34 6D 02 INC (BP+02) ;Yアドレスを1つ BFB36 61 02 80 CMP (BP+02),80H ;ふやし、63回繰り BFB39 1B 2B JRNZ NEXTY1 ;返し BFB3B D8 08 A0 00 01 MV [0A008H],(BP+01) ;Xアドレスをセット BFB40 CC 02 40 MV (BP+02),40H ;Yアドレスの初期値 BFB43 D8 08 A0 00 02 NEXTY2:MV [0A008H],(BP+02) ;Yアドレスをセット BFB48 04 77 FB CALL LOOP ;タイミングをとる BFB4B 88 0B A0 00 MV A,[0A00BH] ;空読み BFB4F 04 77 FB CALL LOOP BFB52 88 0B A0 00 MV A,[0A00BH] ;データを読み込む BFB56 04 77 FB CALL LOOP BFB59 D8 08 A0 00 02 MV [0A008H],(BP+02) ;Yアドレスをセット BFB5E 68 FF XOR A,0FFH ;データを反転して BFB60 04 77 FB CALL LOOP BFB63 A8 0A A0 00 MV [0A00AH],A ;画面に書き込む BFB67 6D 02 INC (BP+02) ;Yアドレスを1つ BFB69 61 02 78 CMP (BP+02),80H ;ふやし、63回繰り BFB6C 1B 2B JRNZ NEXTY2 ;返す BFB6E 6D 01 INC (BP+01) ;Xアドレスを1つ BFB70 61 01 C0 CMP (BP+01),0C0H ;増やし、8回繰り BFB73 1B 6D JRNZ NEXTX ;返す BFB75 3F POPU IMR ;割り込み許可 BFB76 07 RETF ;BASICに戻る BFB77 06 LOOP: RET 10:POKE &HBFB00,&H2F,&H30,&HCC,&HFB,&HA0,&HCC,&H01,&HB8,&HD8 ,&H04,&HA0,&H00,&H01,&HCC,&H02,&H40 20:POKE &HBFB10,&HD8,&H04,&HA0,&H00,&H02,&H04,&H77,&HFB,&H88 ,&H07,&HA0,&H00,&H04,&H77,&HFB,&H88 30:POKE &HBFB20,&H07,&HA0,&H00,&H04,&H77,&HFB,&HD8,&H04,&HA0 ,&H00,&H02,&H68,&HFF,&H04,&H77,&HFB 40:POKE &HBFB30,&HA8,&H06,&HA0,&H00,&H6D,&H02,&H61,&H02,&H80 ,&H1B,&H2B,&HD8,&H08,&HA0,&H00,&H01 50:POKE &HBFB40,&HCC,&H02,&H40,&HD8,&H08,&HA0,&H00,&H02,&H04 ,&H77,&HFB,&H88,&H0B,&HA0,&H00,&H04 60:POKE &HBFB50,&H77,&HFB,&H88,&H0B,&HA0,&H00,&H04,&H77,&HFB ,&HD8,&H08,&HA0,&H00,&H02,&H68,&HFF 70:POKE &HBFB60,&H04,&H77,&HFB,&HA8,&H0A,&HA0,&H00,&H6D,&H02 ,&H61,&H02,&H78,&H1B,&H2B,&H6D,&H01 80:POKE &HBFB70,&H61,&H01,&HC0,&H1B,&H6D,&H3F,&H07,&H06 90:CALL &BFB00:GOTO 90 さて、どうでしょうか。マシン語の最後にあるRET命令のみのサブルーチ ンは元々は、タイミングをとるためのプログラムが入っていましたが、なくて もタイミングがとれるので、(とはいってもサブルーチンコールまで取るとタ イミングがとれない)RET命令のみ残しているわけです。本当はこのような プログラムを作ることはおすすめできません。これはもし、PC−E500シ リーズの高速版が出たとき(または、自分ででX’TALを交換したとき)に もプログラムを正常に動かすことができなくなるかも知れないからです。でも 特に高速さが要求されるゲームなどでは、ぎりぎりのタイミングで動くように することもあります。また、プログラムを作ってからわかったことですが、画 面のデータを読み込むときは1回空読みをしなければならないようです。また、 上のインジケータも反転させているのはこうしないと画面に線が入ってしまう ためです。(原因不明)  マシン語をつかっているにもかかわらず、ちょっと遅く感じますね。もっと 速くしたい人は、一度に画面データを全部読み込んで、一気に書き込むように 改造してみて下さい。(このプログラムでは、1つづつ読み込んで、1つづつ 書き込むようになっている) 4.12 音だし  次は、マシン語で音出しをしてみましょう。BASICではBEEPという 命令を使って簡単に音を出すことができます。しかし、このBEEP命令ちょっ と音域が狭いように気がします。そこでマシン語を使って、BEEPと同じ様 なことをやってみます。 BFB00 2F START:PUSHU IMR ;割り込み禁止 BFB01 30 CC FB A0 MV IMR,0A0H BFB05 D1 01 80 FB 0B MVW (BP+01),[0BFB80H] ;音程 BFB0A 8A 82 FB 0B MV BA,[0BFB82H] ;音長 BFB0E 83 01 LOOP: MV I,(BP+01) BFB10 30 79 FD 10 OR (0FDH),10H ;ブザーON BFB14 EF WAIT ;音程の時間だけ待つ BFB15 83 01 MV I,(BP+01) BFB17 30 71 FD EF AND (0FDH),0EFH ;ブザーOFF BFB1B EF WAIT ;音程の時間だけ待つ BFB1C 7C 02 DEC BA BFB1E 1B 12 JRNZ LOOP ;音長回繰り返し BFB20 3F POPU IMR ;割り込み許可 BFB21 07 RETF ;BASICに戻る 10:POKE &HBFB00,&H2F,&H30,&HCC,&HFB,&HA0,&HD1,&H01,&H80,&HFB ,&H0B,&H8A,&H82,&HFB,&H0B,&H83,&H01 20:POKE &HBFB10,&H30,&H79,&HFD,&H10,&HEF,&H83,&H01,&H30,&H71 ,&HFD,&HEF,&HEF,&H7C,&H02,&H1B,&H12,&H3F,&H07 30:POKE &HBFB80,40,0,0,10:CALL &BFB00 &HBFB80からの2バイトに音の高さ、&HBFB82からの2バイト に音の長さを入れてコールします。さて、リストを見てもらえばわかるとおり、 ブザーをONにするためには、&HFDにあるシステム・コントロール・レジ スタ(以下SCRと略)のビット4を1にすれば良いのです。またブザーをオ フにするには、SCRのビット4を0にすれば良いのです。(苦労して調べた のにSC61860と同じコントロール・ポートのビット4だったとは。)と ころで、このブザーONのときにSCRのビット5もついでにONにすると周 波数約4KHzの音が出るようになります。(BEEPで音程を省略したとき と同じです。)また、わざわざ割り込みを禁止しているのは、割り込みがかか ると音が濁ってしまうためです。注意として、SCRにおかしな値を書き込む とポケコンが暴走(オールリセットも効かない!故障したかと思った。万が一 このような事態になったら電池を抜いてしばらく放っておくこと。)すること があるので注意して下さい。 4.13 リロケータブルなプログラム  いままでここに載せてきたプログラムは、できるだけプログラムのおかれた アドレスに依存しない、つまりリロケータブルにしたつもりです(残念ながら 画面反転はリロケータブルではありません)ここでは、リロケータブルなプロ グラムを作るためのテクニックを紹介したいと思います。  プログラムがアドレスに依存してしまう原因は、おもにジャンプ命令とコー ル命令です。ジャンプ命令には相対ジャンプ命令というのがあって、これを使 えばアドレスに関係ないプログラムを作ることができますが、±255バイト 以内にしかジャンプできないという欠点があります。そこで、256バイトを 越えた相対ジャンプの方法を紹介しましょう。実は、BASICのCALL命 令によってマシン語プログラムが実行されたときは、Yレジスタにプログラム の先頭番地が入っているのです。(JP Yによって、マシン語のプログラム に飛んでいる)従って、プログラムの先頭からの相対番地がわかっていれば、 次のような方法で相対ジャンプができるのです。 相対アドレス 00000 A5 01 MV (BP+01),Y ;Yレジスタの値を保存 01000 85 01 MV Y,(BP+01) ;Yレジスタに値を戻す 01002 0C 00 20 00 MV X,02000 ;Xレジスタに相対アドレス 01006 45 45 ADD X,Y ;アドレスを計算 01008 11 04 JP X ;ジャンプ 02000 ・・・・・・・・・・ ;プログラムの続き これは、あくまで例ですがこのように(プログラム先頭番地+相対アドレス) を計算して、間接ジャンプをすればどの様な場合にも適応できるはずです。  つぎに相対コールですが、これも全く同じようにすることができます。まず、 システムスタックにサブルーチンから戻ってきたときに実行するアドレスをプッ シュします。次にコールアドレスを相対ジャンプと同じように計算して、間接 ジャンプします。次の例を見て下さい。 相対アドレス 00000 A5 01 MV (BP+01),Y ;Yレジスタの値を保存 01000 85 01 MV Y,(BP+01) ;Yレジスタに値を戻す 01002 0C 00 20 00 MV X,01012 ;Xレジスタに戻り先の相対アドレス 01006 45 45 ADD X,Y ;戻り先アドレスを計算 01008 B4 37 MV [--S],X ;戻り先アドレスをスタックにプッシュ 0100A 0C 00 20 00 MV X,02000 ;Xレジスタに飛び先の相対アドレス 0100E 45 45 ADD X,Y ;飛び先アドレスを計算 01010 11 04 JP X ;ジャンプ 01012 ・・・・・・・・ ;プログラムの続き 02000 ・・・・・・・・・・ ;サブルーチン 020FF 07 RETF ;リターン ざっと、こんな具合いです。ただし、サブルーチンからのリターンはRET ではなくRETF命令を使う必要があります。 4.14 64キロバイトの壁は厚かった  SC62015は1Mバイトのメモリー空間があります。さて、PC−E5 00シリーズに64KBラムカードを取り付けたとします。次のプログラムは 正常に動くでしょうか。 7FFF8 88 80 FB 0B START:MV A,[0BFB80H] ;&HBFB80の内容と 7FFFC 89 81 FB 0B MV IL,[0BFB84H] ;&HBFB84の内容を 80000 46 01 ADD A,IL ;足して 80002 A8 82 FB 0B MV [0BFB88H],A ;&HBFB88にいれる 80006 9F RC 80007 07 RETF ;BASICに戻る  これはこの章の一番最初に出てきたプログラムを、アドレスを変えただけの ものです。プログラムをみただけですとちゃんと足し算をするようですが、た ぶん暴走してしまうと思います。(ラムカードを持っていないので確かめよう がない。)これはSC62015のプログラム・カウンタはPCレジスタとP Sレジスタの2つに分かれていることによります。  PCレジスタはNEARジャンプ・相対ジャンプ・NEARコールなどによっ て書き換えられます。また、その他の命令を実行しても、次の命令をさすよう に書き換えられます。しかし、PSレジスタの方はFARジャンプ・FARコー ル命令を使わなければ決して書き換えられません。  この場合、まずPSレジスタが7H、PCレジスタがFFF8Hでプログラ ムがスタートします。そして、命令が実行されるとPCレジスタがFFFCH に書き変わるので7FFFCHにある命令を読み込むことになります。ここで 問題が起こります。この命令が実行された後にPCレジスタがFFFCH+4 H=10000となり、オーバーフローが無視されて、0になります。しかし、 PSレジスタの方はやはり7のままですので、つぎに読み込まれるのは800 00Hではなく70000Hにある命令になります。ここはデータエリアになっ ているはずですので、たぶん暴走するでしょう。  したがって、64KB以上のマシン語のプログラムを作るときには、64K Bの壁に注意する必要があるということです。CPUをこのようなおかしな構 造にしたのはおそらくプログラムの長さを短くするためであると考えられます。 ほかのCPUでも例えば16ビットCPUである8086でさえ、8ビットC PUからの移行性を考えてセグメント・レジスタというこのCPUのPSレジ スタに当たるものを持っているのですから我慢しましょう。 4.16 これからの課題  さて、これまでPC−E500シリーズのCPUであるSC62015につ いて解説してきたわけですが、マシン語でプログラムを作るにはさらにいろい ろなことを知っている必要があります。まず、マシン語を操るテクニックが必 要です。これには、市販の解説書をみればいろいろなことがわかるはずです。 (たとえCPUが違っても)。次には、ハードウェアの事を良く知っておく必 要があります。たとえ、マシン語の命令を知っていても、画面の制御方法を知 らなければ画面に文字や絵を表示させることができないのです。一応PC−E 500シリーズの解説書はありますが、大したことは書いていないので、皆さ んが自分で解析などをして調べる必要がある場合もあるでしょう。(解析の仕 方については第4部参照。)もし、解析で重要なことがわかったときは、ぜひ なんらかの方法で発表して下さい。 第2部 その他のポケコン  第1部ではPC−E500シリーズについて長々と述べてきたわけですが、 だからといってそれまでの機種を見捨てたわけではありません。いちおう題名 は「PC−E500うらわざ大事典」ではありませんので。それではもうすで に過去の機種となってしまったものの裏わざを見ていくことにしましょう。 (何を今更という気もしないではありませんが……) 第1章 PC−1251  もうこんな機種の事を覚えている人はいないでしょう。この機種には山ほど 隠しコマンドがあったので楽しめました。(ただし、ほとんどエラーになって しまうのですが。)今ではシャープ公認になっているPEEK、POKE、C ALL、CSAVE M、CLOAD Mもこのころは隠しコマンドになって いました。 1.1 PC−1251の隠しコマンド  PC−1251の隠しコマンドのうちで有用なのは、すでにメーカー公認に なってしまった上の5つのコマンドぐらいしかありません。ほかの隠しコマン ドはなにかのハードウェア(RS−232Cや専用ROMなど)のためのもの らしいのですが、そのハードウェアが存在しないために意味をなさないものに なっています。 ERROR:用途不明。ひょっとするとON ERROR文にするつもりだっ たのかも知れません。今では、単にERROR 1を出す命令に過ぎません。 DEBUG:用途不明。PC−1211にDEBUG命令というのがあります が、これをPC−1251でも使おうとしたのでしょう。しかし実際には使う ことはできず、ERROR 1になります。ちなみにPC−1211のDEB UG命令は、TRON+RUNの意味を持っています。(自動的にデバッグを してくれる命令だったら良かったのに) KEY:これも全く意味不明。KEY ONとかKEY OFFとかするとE RROR 8になりますから、きっとI/O関係の命令なのでしょう。 ROM:用途不明。どうやらこれは、実行専用ポケコンと関係がありそうです。 PB−100にROM OFFというプログラムROMを切り放す命令がある のでそれと同等のものと思われます。 SETCOM:RS232Cインターフェイスの条件を設定する命令です。書 式は次の通りです。 SETCOM ボーレート,パリティ,ビット長,ストップビット,デバイス  ただし、ボーレートは110,300,1200しか指定できません。11 0ボーの機器なんて余り見かけませんが、これはTTY(テレタイプ)やテレッ クスで使われているものです。デバイスには、CO,CI,PO,KIがあり、 それぞれカセット出力、カセット入力、プリントアウト、キー入力を示してい ます。しかし、PC−1251にはRS232Cインターフェイスがないので 宝の持ち腐れとなってしまっています。(RS232C関係の命令はすべてE RROR 8になります) COM$:RS232Cインターフェイスの設定内容を見る関数です。SET COMで設定した内容がみられるはずなのですが。インターフェースが存在し ないためにERROR 8になります。 INSTAT:RS232Cの状態を見る関数です。 OUTSTAT:RS232Cの状態を設定する命令です。  以上が隠しコマンドの全てです。これを知っていれば、あなたも今日からP C−1251通の仲間入り!………なわけないですね。 1.2 やっぱりマシン語  PC−1251は素直な機械ですので、マシン語を使うのは比較的楽なはず です。(SC61860のマシン語が理解できればの話。私は、使いたいとも 思わないけれど。)もう、すでにたくさんの人がPC−1251について解析 して、たくさんのマシン語のプログラムを発表しているので、特にここではプ ログラムを発表したりはしません。(というより恥ずかしくて発表なんかでき ない。)ここではただ1つROM内ルーチンを発表するだけにします。それは &4009から始まるルーチンです。BASICからCALL文で呼び出すこ ともできます。これは何をするルーチンかといいますと、RAMをすべて初期 化してしまうのです。(NEWよりたちが悪い)新しいマシン語のプログラム を入力する前に実行するといいと思います。 1.3 PC−1251は永遠に不滅かな?  発売からもう6年が過ぎたPC−1251ですが、私のPC−1251はま だ現役バリバリです。これもすべて、本体は手帳型、フルセットでもA5サイ ズというコンパクトさのおかげだと思います。すでにプログラムテープは4本 目になってしまいました。やはりここにポケコンの本来の姿があるのでしょう か。 第2章 PC−1500/1600K  この2つのシリーズは、シャープのほかのポケコンとは全く別のシリーズを 形成しています。それはCPUの違いからくるもので、周辺機器などはほかの シリーズとは全く別のものを使わねばなりません。そのために今では余り人気 がないようです。けれども、現在でもPC−1600Kがシャープのポケコン の最高峰として位置づけられているように今でも新製品に負ける事なく働くこ とができます。この章ではこのシリーズのポケコンを使いこなす上でのワンポ イントを挙げたいと思います。 2.1 小文字を入力したい  PC−1500/1600シリーズでは、通常文字は大文字で入力されます。 小文字を入力させたいときには、いちいちSHIFTを押さなければなりませ ん。ところが、LCDの上の方を良くみると、SMALLと言うインジケータ があるのがわかります。これをつければひょっとするとダイレクトに小文字が 入力できるかも知れません。それではSMALLインジケータをつけてみましょ う。 PC−1500:POKE &764E,PEEK &764E OR 8 PC−1600:XPOKE &764E,XPEEK &764E OR 8 または:POKE &F64E,PEEK&F64E OR 8  さて、SMALLインジケータをつけたら小文字がダイレクトに入力できる のでしょうか。PC−1500の人はちゃんと小文字が入力できたはずです。 PC−1600の人は残念ながらこれでは小文字を入力することはできないの です。PC−1600の人でどうしても直接小文字の入力がしたいのなら、キー テーブルを書き換えるしかありません。PC−1500の人でもかなの部分の キーテーブルを書き換えて、直接キーボードから入力できない文字を入力する ことができます。複雑なのでここでは書きませんが、知りたい人は参考文献を 見て下さい。 2.2 電池がもったいない...  PC−1500/1600シリーズはものすごく電気を食います。(PC− 1501で0.13W、PC−1600Kで0.47W!ちなみにPC−12 11は0.011W)だから、まさか電池だけで使っている人は少ないと思い ます。(本体にACアダプタの端子がついていますから。)電池だけで使って いるとき、またはアダプタを使っているときでもプログラムをいったん中断し て、また後で中断したところから再開させたいときがあるでしょう。ところが、 ポケコンはいったん電源を切ってしまうとプログラムの再開ができなくなって しまいます。ただ、オートパワーオフが働いたときは、プログラムの再開がで きるようになっています。それでは、強制的にオートパワーオフをすることは できないのでしょうか。PC−1600では次のようなコマンドがあります。 POWER AOFF  PC−1600のPOWER AOFF命令は、本来はオートパワーオフを するかどうか設定する命令になっていますが、このようにすることで強制的に オートパワーオフ状態にすることができます。PC−1500ではこのような コマンドはありません。しかし次のようにすることで同じ様な働きをさせるこ とができます。 CALL &E33F  PC−1600で実行する場合はXCALLを使って下さい。これを実行す るとすぐに電源が切れます。このときONを押して電源をいれたときにプログ ラム実行状態になっていますので、何かキーを押して下さい。 2.3 RS232Cの高速化  PC−1500用のRS232CインタフェースであるCE−158は最大 ボーレート2400ボーまでしかサポートしていません。これを高速化してみ ましょう。まずSETCOMでボーレートを2400ボーにしてから次のよう に操作します。 POKE# &D008,PEEK# &D008 AND &E0 POKE# &D00E,PEEK# &D00E OR &40 AND &7F  これでボーレートは倍の4800ボーになったはずです。 2.4 PC−1500/1600ばんざい  PC−1500やPC−1600についても、数多くの資料が発表されてい ます。特に、PC−1500機械語の手引という本は、シャープが直接公表し た資料で、内容はCPUの構造からマシン語によるサンプルプログラムまでと 痒いところに手が届く本です。しかし、メーカーからこのような本が出たのは 最初で最後でした。やはりメーカーは、自社の製品の内容や構造についてユー ザーに公表する義務があるのではないでしょうか。PC−1600Kのときは、 自分で解析を始めましたが、なんせ2重バンク切り替えというトンでもないこ とをやっているために挫折してしまいました。今後、このシリーズのポケコン の新製品が出るのかどうかわかりませんが、その際には、ぜひ資料を公開して 欲しいものです。 第3章 PC−1470U/1475  PC−1470U/1475については、前回のポケコン裏わざ大事典にお いて裏技を発表しましたので、今回はそれから発見されたことを中心に述べて いきたいと思います。 3.1 またまたかくしコマンド?  どうやらPC−1470U/1475にもかくしコマンドがあるようです。 まず一つ目は、3乗を求めるCUB関数です。私は、この関数をマニュアルに 載っているものとばかり思っていましたが、どこにも書いていないようです。 そして、二つ目はランダムファイル操作命令です。このランダムファイル操作 命令には次のようなものがあります。 FIELD:ランダムバッファを変数に割り当てる命令 PUT  :1レコードをファイルに書き込む命令 GET  :1レコードをファイルから読み出す命令  使い方は、マイコン用のBASICとほぼ同じで、まず、OPEN ”ファ イル名” AS #ファイル番号でファイルを開きます。(FOR モードは 省略すること)つぎに、FIELD #ファイル番号,バイト数 AS 変数 名,………でランダムバッファを変数に対応させます。PUT #ファイル番 号,レコード番号でディスクに書き出し、GET #ファイル番号,レコード 番号でディスクから読み込みます。なお、このとき変数に値を代入するにはL SET、RSET命令を使うのが無難です。 3.2 WORってなに?  実はこのことは私が発見したわけではありません。次のように入力してみて下さい。 1 WOR 2  WORなんて関数はないからエラーが出ると思うでしょう。ところがどっこ いポケコンは次のように解釈してしまいます。 1 XOR 2 3.  いったいどうなっているのでしょう。どうやらBASICの入力ルーチンに バグがあるようです。 3.3 ハードウェア・チェック  どうやら、PC−1470U/1475のROMの中には、自己診断ソフト が載っているようです。次の様に操作してみて下さい。 CALL &1100  うまくいかなかった人は、一度オール・リセットして下さい。 3.4 PC−1470Uその後  実は、私のPC−1470Uは電池が切れたままです。PC−E500を使っ ている今では、今更PC−1470Uなんてという気がしています。でも、実 の所、電池が高すぎるというのが最大の理由になっています。電池を交換する と900円も取られてしまうわけですが、現在うちでは3台が電池切れですの で全部交換すると2700円もかかってしまいます。やはりポケコンを買うと きは、ランニングコストまで考えておく必要があるようです。ところで、前回 の大事典でたくさんPC−1470Uのサンプルプログラムを作ったのですが、 実際に使われているのを見たことがありません。そんなに難しかったのでしょ うか...。 第3部 プログラムを使うために  今度は、実際にプログラムを作ったり、移植したり、また人のプログラムを 入力したりするときは注意する点を見て行きましょう。 第1章 プログラムを作る  プログラムを作るのは非常に難しいことです。しかし、こつさえつかめれば 誰にでもできることです。この章では、どうしたらプログラムが作れるのかを 考えて行きたいと思います。 1.1 仕様を決定しよう  当然プログラムを作るからには目的があるはずです。ここでいいたいのは、 その目的をはっきりと、具体的に仕様という形にまとめる必要があるというこ とです。たとえば、ただゲームがしたいとか神経衰弱が作りたいとかいう抽象 的な目的があるだけでは、なんの進展もありません。神経衰弱を作るけれどキー 操作はこうで、ゲーム展開はこういうふうにするとかいった具体的な仕様が決 まれば、すんなりとプログラムを作ることができるのです。もっというと、こ の段階でどれだけの入力をして、どれだけの結果を表示するかを決めておく必 要があります。これを決めておかないと、プログラム作成中にどんどん欲が出 てきて、最終的には何をやっているのか自分でもわからないプログラムができ てしまいます。 例 +---------------------------------------------------------------------+ | 神経衰弱ゲーム | | | | 4人でゲームをするがそのうち3人分はコンピュータの担当 | | コンピュータの手は次のようにする | | 1.同じ数字が出ているかどうかを調べて、あるならその一つをめくる | | 2.なかったときは乱数で選ぶ | | 3.めくったカードと同じカードが出たかを調べる | | 4.出ていたら、ある確率でもう一枚のカードをめくる | | 5.それ以外ならば乱数でめくる | | 人間側は2468のキーでカードを選びリターンで決定する | | 画面には全部のカードと何枚カードを持っているのかを表示する | |        ............. | +---------------------------------------------------------------------+ 1.2 ブロックに分割する  さて仕様が決まると、次はどの様にして仕様を実現するかを考えなくてはな りません。この手段をアルゴリズム(算法)といっています。その際に、頭か らだらだらとプログラムを書いていくよりも、仕事の区切り毎にプログラムを 分けて考えると楽になります。例えば、神経衰弱の場合ですと、画面にカード を出す部分とか、めくるカードを選ぶ部分とかに分けるということです。 1.3 制御構造はしっかりと  さて、プログラムを書く際になって、この制御構造をしっかりと考えておか ないと、あっちにいったりこっちに行ったりといういわゆるスパゲティプログ ラムになってしまいます。それには、各制御構文の特徴をしっかりとつかんで おく必要があります。ポケコンのBASICの制御構文について一つづつ見て いきましょう。 GOTO文  制御構文の中では一番オーソドックスですが、その手軽さ故に乱用される傾 向があります。IF ELSE構文が使えない機械では、ELSEの代わりに GOTO文でほかのところに飛ばしたりしますが、そのほかの場合ではなるべ く使わないのが懸命でしょう。また、使うときでもラベルを使ったりして意味 がわかるようにしておくのも手でしょう。 IF THEN ELSE  条件によってプログラムを分岐します。機械によっては、THENの直後に 代入文がくるときはLETを使う必要があります。ELSEが使えない機械で は、GOTOを使わなくても済むように条件を逆にしてみたりすると良いでしょ う。 FOR NEXT  ループに使う構文ですが、一つだけ注意することがあります。それは、ルー プ中からGOTOなどで飛び出してはいけないということです。FOR NE XTではどこからどこまでループするかを記憶しています。ここでGOTO文 でループから飛び出してしまうと、記憶場所がそのままで残ってしまいます。 これを何回か繰り返すとしまいに記憶場所がなくなってエラーが発生します。 これと同じ理由で、ループ中にCLEARを実行してはいけません。どうして もループから脱出したいときは、FOR NEXTの代わりにIF THEN を使って下さい。 GOSUB RETURN  サブルーチンコールをします。特に注意はありません。 1.4 変数を管理しよう  さて、プログラムをコーディングする際に、気を付けなければならないこと があります。それは変数をきちんと管理することです。BASICでは一般の プログラム言語と異なり、変数は宣言する必要がありません。(C、PASC ALでは変数は宣言しないと使えません)そのためにうっかりして同じ名前の 変数を別の目的に使ってしまうことがあります。そういうことが起きないよう にするためには、使う変数名とその目的をしっかり管理しておく必要がありま す。また、プログラムは正常にできていても、これをポケコンに入力するとき に間違えてしまうこともあるので注意しましょう。 1.5 マシン語のプログラムを作る(ハンドアセンブル)  これまで、おもにBASICのプログラムの作り方を述べてきましたが、マ シン語の場合もほとんど変わりありません。ただ、マシン語の場合普通はニモ ニックを使ってプログラムを書くのでこれをマシン語に変換しなければなりま せん。普通ニモニックをマシン語に変換するにはアセンブラを使います。しか し、アセンブラがないときには人間の手でアセンブルをしなければなりません。 (これをハンドアセンブルという)  それでは実際にハンドアセンブルをしてみましょう。例えば次のようなプロ グラムがあったとします。(SC62015の場合です、プログラム自体には 全く意味はないので決して実行したりしないように!) START:MV (0EAH),0 PUSHU IMR MV X,0A000H MV A,255 MV IL,10H LOOP: MV [X++],A DEC IL JRNZ LOOP POPU IMR MV (0EAH),8 RETF  このプログラムをハンドアセンブルしてみます。まず、コード表をみて、各 命令をマシン語に変換します。10進法の数値と16進数の数値を混乱しない ようにして下さい。このときにプログラム中へのジャンプ・コール命令はアド レスが未定ですので書きません。同じ理由で相対ジャンプ命令のオペランドも まだ書けません。なお、SC62015ではプレバイトの処理があるので注意 して下さい。 30 CC 00 START:MV (0EAH),0 ←30はプレバイト 2F PUSHU IMR 0C 00 A0 00 MV X,0A000H 08 FF MV A,255 ←10進の数値は16進にする 09 10 MV IL,10H B0 24 LOOP: MV [X++],A 7C 01 DEC IL 1B ?? JRNZ LOOP ←相対ジャンプのオペランドは未定 3F POPU IMR 30 CC 08 MV (0EAH),8 ←30はプレバイト 07 RETF 次にアドレスを書き加えます。このときに先ほどオペランドが未定で書けなかっ たところもきちんと勘定しなければなりません。 BFB00 30 CC 00 START:MV (0EAH),0 BFB03 2F PUSHU IMR BFB04 0C 00 A0 00 MV X,0A000H BFB08 08 FF MV A,255 BFB0A 09 10 MV IL,10H BFB0C B0 24 LOOP: MV [X++],A BFB0E 7C 01 DEC IL BFB10 1B ?? JRNZ LOOP ←??のところを飛ばさないように BFB12 3F POPU IMR BFB13 30 CC 08 MV (0EAH),8 BFB16 07 RETF  そして、ジャンプ・コール命令のオペランドを書き、最後に相対ジャンプの オペランドを計算します。これはCPUによって異なるのですがSC6201 5の場合は(飛び先のアドレス−ジャンプ命令の次のアドレス)で計算します。 (当然マイナスの場合はこの逆) BFB00 30 CC 00 START:MV (0EAH),0 BFB03 2F PUSHU IMR BFB04 0C 00 A0 00 MV X,0A000H BFB08 08 FF MV A,255 BFB0A 09 10 MV IL,10H BFB0C B0 24 LOOP: MV [X++],A BFB0E 7C 01 DEC IL BFB10 1B 06 JRNZ LOOP ←&HBFB12-&HBFB0C=&H06 BFB12 3F POPU IMR よってオペランドは06 BFB13 30 CC 08 MV (0EAH),8 BFB16 07 RETF 1.6 プログラムを走らせてみる  さて、プログラムができたでしょうか。できた人は、とりあえずおめでとう ございます。とりあえずというのは、実はこれからが大変だからです。普通、 人が作ったプログラムにはなんらかの間違いがあるものです。この間違いの事 をバグと呼んでいます。でも、しっかりと構造を考えて作ったプログラムなら すぐに発見できるはずです。ただ、勘違いというのはなかなか発見できません ので、気分転換をするのも手だと思います。バグの取り方については、4章を みて下さい。 第2章 プログラムを移植する  この章では、いいプログラムがあるんだけれどほかの機種用であるとか、自 分でプログラムを作るのは面倒だからほかの機種のプログラムを使いたいとい うときにどの様にすれば良いのかを述べていきます。 2.1 敵を良く知れ  ほかの機種のプログラムを移植するときには、元のプログラムの走る機種に ついて知らなければなりません。とりあえず、現在使われているBASICが つかえるポケコンを次に挙げます。(これらの情報は、各社のカタログ及びP Jによるものです。残念ながらカシオのマシンは良くわからないので代表機種 のみです。またここからの事もシャープの機種が中心になります。) 1.シャープのポケコン A1グループ PC−1210/1211  1980年に発売された日本初のBASICが使えるポケコン。但し、演算 速度はいように遅い。(おそらく世界最低速度のBASICではなかろうか? FORループ1回まわるのに1秒かかる。)24桁の液晶表示機を持っている が、なんとバックが黄色である。(当時はこのような液晶しかなかったのです。) BASICは原始的なもので、命令数もかなり少ない。メモリー容量はPC− 1210が400ステップ、PC−1211が1424ステップである。なお この機械ではマシン語を使うことができない。(なのに暴走させることはでき る。なぜだろう?) A2グループ PC−1250/1251/1255  PC−1211の後継機として、1982年に発売されたポケコン。ポケコ ンとしては驚異的な手帳サイズを実現。但し、その結果としてキーが非常に小 さく、取扱には注意が必要である。なお、この3機種のうち、PC−1255 はほかの機種より遅く1983年になってから発売された。これらの機種も2 4桁の画面を持っている。また、この機種ではマシン語を使うことができる。 メモリー容量は、PC−1250で1438バイト、PC−1251で346 8バイト、PC−1255では9630バイトとなっている。 PC−1245(G)  PC−1250シリーズの親戚的な関係にあるBASICの学習用ポケコン。 画面が16桁しかないことを除けばPC−1250シリーズの大部分のプログ ラムが実行できる。また、キーに文字列を登録するリザーブ機能もついていな い。また、学校用としてPC−1245Gというのがあったようである。(よ く知らない)メモリーは1486バイト。 A3グループ PC−1260/1261/1262  PC−1250シリーズの後継機的な存在にある24桁二段表示の手帳型ポ ケコン。このシリーズの特徴として、HELP機能やビジネスシミュレーショ ン(数式記憶機能のようなもの)があることが挙げられる。また、これらの機 種ではかなやアルファベット小文字を使うことができる。なお、このうちPC −1262だけが86年になってから発売されている。このPC−1262は PC−1261とほぼ同じものである。メモリー容量はPC−1260が31 98バイト、PC−1261/1262が9342バイトである。 A4グループ PC−1246/1247  PC−1245の流れをくむBASIC学習用のポケコン。このA4グルー プやC2グループに属する機種では、スピードアップのためにCPUが4ビッ トの高速タイプのものに変更されている。そのために、マシン語を使うことは できない。このシリーズも16桁の液晶表示機を持っている。なお、PC−1 246にはBEEP機能が存在しないので注意が必要である。メモリー容量は PC−1246が1278バイト、PC−1247が3326バイトである。 PC−1246S/1248  PC−1246シリーズの後継機。この2機種では、持ち運びの際にキーが 引っかかるのを防ぐためか、タッチ式のキーになっているので、表面がほぼ平 らである。なお、PC−1246SにもBEEP機能はない。メモリーのフリー エリアは、PC−1246Sで1278バイト、PC−1248で9470バ イトである。 PC−1246DB/1248DB  PC−1246Sシリーズの後継機であるデータベース機能付きポケコン。 この2機種でも、キー面が平らになっている。画面は16桁。PC−1246 DBには毎度のことながらBEEPがない。また、この2機種ではかなを使う ことができる。注意すべき点としては、入門用のためBASICの命令が非常 に少なく、RND関数やSIN関数などもないので、実用に使うには不十分で あろう。メモリー容量はPC−1246DBが1278バイト、PC−124 8DBが9470バイトである。 B1グループ PC−1350  ビジネス用に作られた24桁四段表示のポケコン。この機種より、RAMカー ドシステムが使われている。また、シリアルインターフェイスがついているの で、ほかの機種との通信が可能になった。またグラフィック機能も充実してい て、150*32ドットの画面に、線を引いたり点を打ったりすることができ る。メモリー容量は標準で3070バイトである。 PC−2500(S)  PC−1350とほぼ同じ機能を持つプリンタ・プロッタ付きポケコン。P C−2500Sのキーボードは、ポケコンというよりも、マイコンに近い形を していて、テンキーのほかに数字キーがあったり、SHIFTキーの使い方も、 SHIFTキーを押しながら使うというふうになっていた。メモリーは標準で 3102バイト。 B2グループ PC−1360(K)  PC−1350の後継機として登場した漢字も使えるポケコン。但し、漢字 が使えるのはPC−1360Kのみであり、PC−1360では使えない。画 面表示はANKモードで24桁*4段、PC−1360Kの漢字モードで、1 9桁*2段(漢字の場合は9桁*2段)である。グラフィック機能はPC−1 350と同じである。また、この機種ではCE−140Fを使うことができる。 但し、BASICの構造が変わっているために、PC−1350のプログラム を直接ロードすることはできず、ロード時にPC−1360に対応するように 変換をしている。メモリー容量はRAMカードに依存し、付属の8KBラムカー ドを取り付けている場合6558バイトのユーザーエリアがある。 番外 PA−7C18/19  電子システム手帳PA−7000〜8600で使うことができる、プログラ ムBASICカードである。BASICの仕様はPC−1360とほぼ同じで あるが、実行専用機で動かすために一部仕様強化がなされている。なお、プロ グラムの開発にはMS−DOSの走るマイコンが必要である。メモリーはPA −7C18が32キロバイト、7C19が64キロバイトである。 C1グループ PC−1401/1402  関数電卓機能付きポケコン。表示は16桁。PC−1402はPC−140 1の後継機として作られたが、メモリーを除いて全く同じ仕様である。但し、 PC−1401の初期型は、FACT、DECI関数がFAC、DECになっ ているので注意が必要である。(実はバグ取りのために命令を変更した。)メ モリー容量はPC−1401が3534バイト、PC−1402が9678バ イトである。 C2グループ PC−1431  4ビットCPUの登載により、低価格を実現した関数ポケコン。但し、電卓 モードがなくなっている。スピードは速いが、一部の特殊な関数が削られてい る。表示は16桁。フリーエリアは3302バイト。 PC−1404G/1405G  高校、専門学校用に作られたポケコン。PC−1431と同じく特殊な機能 を削って価格を抑えている。また、この2機種はシャープのポケコン中唯一単 三電池2本で動いている。表示機は16桁。メモリーその他は不明。(一度見 せてもらったことはあるのですが。) PC−1415G  PC−1405GをPC−1431並にした機種と思われるが、詳しいこと は不明。 C3グループ PC−1440  PC−1401シリーズに当時の情報処理技術者試験で使われていたCAP Xの機能を登載したポケコン。関数が、コンピュータ用に作り替えられていて、 CALモードでは、2進数の計算や、AND、OR、XORなどの計算をする ことができる。但し、PC−1440の初期型では、電源をいれると同時にフ リーエリアをクリアしてしまうものがあるので注意が必要である。また、CA PXを使うときにもフリーエリアをクリアしてしまうので、マシン語のプログ ラムをいれるときは注意が必要である。表示は24桁。フリーエリアは350 0バイト。 PC−1416G  PC−1415GとPC−1440を足して2で割ったようなポケコン。詳 しいことは良くわからない。 PC−1445  情報処理技術者試験で使われている言語がCAPXからCASLに変わった のにともない、PC−1440をCASL対応にしたポケコン。表示は24桁。 フリーエリア7372バイト。 PC−1417G  PC−1416GをCASL対応にしたものと思われる。詳しいことは不明。 C4グループ PC−1450  PC−1401シリーズに、RAMカード機能やシリアルポートをつけたポ ケコン。BASIC自体は、PC−1401とPC−1350の良いところを 足したようなものである。また、PC−1400系でもこの機種からかなが使 えるようになった。画面は16桁。メモリー容量は、付属の4キロバイトRA Mカードをつけたとき、3070バイトである。 PC−1460  PC−1450に、行列演算機能を登載したポケコン。PC−14シリーズ ではこの機種からCE−140Fを使うことができる。また、RENUM命令 を使えるようにするために、BASICの構造が大きく変わっている。しかし、 BASICの命令自体はほとんど変わっていない。また、画面が24桁になっ た。フリーエリアは、付属の8KBラムカード時で6878バイトである。 PC−1425  PC−1460の行列演算機能を取り外して、代わりに統計計算、表計算機 能を登載したポケコン。基本的な仕様はPC−1460と同じである。 C5グループ PC−1470U/1475  画面を24桁*2行にした二段表示の関数ポケコン。PC−1460譲りの 行列演算機能と、PC−1425からの統計計算機能を一つにしたようなもの。 また、この機種から倍精度関数がサポートされている。PC−1470Uは、 それに加えてタイマー機能がついているが、大学生協でのみ売られていた。P C−1475はPC−1470Uよりは統計機能が劣っている。また、PC− 1400シリーズでは初めて、PC−1475にリザーブ機能が、PC−14 70Uには数式記憶機能が登載された。メモリー容量は、PC−1470U、 PC−1475とも標準で6558バイトである。 PC−1280  PC−1260シリーズと、PC−1470シリーズを足したようなポケコ ン。名前はPC−1200シリーズではあるが、中身はPC−1400シリー ズの特殊な関数を除いてはPC−1470シリーズと同じものであり、PC− 1470シリーズのソフトのうち、マシン語のプログラムでさえPC−128 0で使えるものも多い。フリーエリアは標準で6558バイト。 C6グループ PC−E200/G801/G811  Z80を登載したポケコン。コンピュータ制御の学習用にI/O機能がつい ているほか、CASL、マシン語モニタなどの機能がついている。また、G8 11にはZ80のアセンブラもついている。表示は24桁*4行。メモリーは、 PC−E200とG811が32KB(フリーエリア30435バイト)、P C−G801が8KBである。 C7グループ PC−E500/E500PJ/1480U/1490U  新設計のCPUを登載したことによってPC−1470シリーズの欠点であっ た速度の遅さを解決したポケコン。但し、BASICは完全に新設計になって いるので、ほかのシリーズからの移植は注意が必要である。画面は40桁*4 行、240*32ドットのグラフィクスができる。PC−E500は、エンジ ニアソフトウェアを、PC−1490Uは「電言板5」のソフトを内蔵してい る。メモリー容量はどれも32KB(フリーエリア28600バイト)である。 Dグループ PC−1500/1501  PC−1210シリーズの次に発売された、高性能ポケコン。ポケコンでは 初めて156*8ドットのグラフィクス機能を登載。また、音階付きBEEP、 オートスタートなど便利な機能を初めて登載した。さらに、この2機種では別 売のCE−156またはCE−157を使うことによってかなを使うことがで きる。PC−1501は83年になってから発売されたが、PC−1600K が発売されるまでの間ずっと販売していた。PC−1500シリーズ独自の機 能は時計機能であり、この機能を使ったソフトはほかの機種には移植できない。 また、PC−1500シリーズの周辺機器はほかのシリーズとは全く互換性が ない。画面は26桁。メモリー容量は、PC−1500が標準で1850バイ ト、PC−1501が5946バイトである。 PC−1600(K)  PC−1500シリーズの後継機として制作された、漢字が使える怪物ポケ コン。PC−1500の機能に加えて、2つのシリアルポート(RS−232 Cと光ファイバーケーブル用SIO)、アナログ入力ポート(AD変換を行う)、 アラーム・ウェイクアップ機能などを登載。PC−1500のソフトを動かす 為にPC−1500コンパチのLH−5803とPC−1600本来のZ80 コンパチCPUの2つのCPUを持っている(実際には周辺用にもう一つCP Uを使っている)という特色がある。画面はANKモードで26桁*4行、漢 字モードで19桁*2行(漢字の場合は9桁*2行)である。メモリー容量は 標準で12090バイトである。 2.カシオのポケコン K1グループ FX−702P  カシオのBASICが使えるポケコン第一弾。当時の対抗機であったPC− 1211よりもかなり速かったところから結構売れたようである。画面は20 桁。メモリー容量は1680ステップ・26メモリーから226メモリー・8 0ステップまで変えることができる。 FX−801P  PC−1251シリーズに対抗して作られた、プリンタ・カセット内蔵のポ ケコン。基本的にはFX−702Pと変わっていない。 K2グループ PB−80/100/100F/110/110V/200/220/300/ FX−700P/802P/5200P  BASICの入門用のポケコン。カシオでは、こんなものを実務に使わせた いらしい。この中でも、初期の機械では、BASICがかなり特殊であるので 注意が必要である。PB−200/FX−5200は手帳型のポケコンである。 PB−300/802Pはプリンタを内蔵している。画面はすべて12桁。メ モリーは、PB−80/100/100F/110/110V/FX−520 0が標準544ステップ(最大1568ステップ)、PB−300/FX−7 00P/802Pが1568ステップ、PB−220が標準1504ステップ である。 PB−400/410/FX−710/720/FX−820P  RAMカードが使えるようになったほかはPB−100シリーズとほとんど 変わっていない。FX−820Pはプリンタ付き。メモリー容量は標準で15 68ステップ。 K3グループ PB−500/FX−740P/750P  メモリー容量がかなり増えたポケコン。PB−500/FX−750Pでは ラムカードスロットを2つ持っている。画面は24桁に拡張されている。また、 PB−500ではかなを取り扱うことができる。メモリー容量は、PB−50 0/FX−750Pが標準4キロバイト、FX−740Pが16キロバイトと なっている。 FX−780P/790P  CAPXが使える折り畳み式のポケコン。画面は24桁。FX−790Pで は3次元配列を使うことができる。また数式記憶機能、データベース機能など も登載。メモリーはFX−780Pが4KB、FX−790Pが標準で8KB である。 FX−795P  FX−790PからCAPX機能を外して、代わりに組み込み演算機能(行 列演算、複素数計算など)を登載したポケコン。またメモリーが16KBに拡 張されている。 K4グループ PB−700/770  PC−1500シリーズの対抗機。20桁*4行の大型画面を持ち、160 *32ドットのグラフィック機能も持っている。また、PB−770ではかな を使うことができる。メモリーは標準で、PB−700が4キロバイト、PB −770が8キロバイトである。 K5グループ FX−860P/841P/840P  32桁*2行の画面を持つカシオのポケコン。FX−860PはFX−79 5Pにあった組み込み演算機能をパワーアップした116種類にも及ぶライブ ラリを登載している。この機能は後のPC−E500のエンジニアソフトウェ アに影響を与えている。FX−841Pは、FX−860Pのライブラリのう ち統計関係のもののみ51種を登載。FX−840Pは情報処理技術者試験に 使われているCASLを登載している。メモリーはFX−860Pが32キロ バイト、FX−841P/840Pが8キロバイトで、共に32キロバイト増 設ができる。 FX−860PVC  FX−860PにCASLを登載。さらにフロッピイディスクを接続できる ようにしたほとんどだめ押し的ポケコン。メモリーは標準で32キロバイト。 FX−870P  FX−860PVCのライブラリ機能を取り外し、そのかわりにC言語を登 載したポケコン。基本的には、ほとんど変わっていないと思っていい。 K6グループ PB−1000(C)  ほかのカシオのポケコンのイメージとは全くかけ離れたところにある高級機。 このシリーズでは表示部にタッチセンサーを内蔵している。PB−1000は ポケコン初のアセンブラ内蔵機である。また、PB−1000Cは、それらの 機能の代わりにCASLを登載している。画面は32桁*4行。メモリー容量 はどちらも標準8キロバイト。 AI−1000  日本初のマルチランゲージポケコン。標準でLISPが登載されているが、 ROMかーどを交換することにより、BASIC、CASL、PASCAL、 Cなどが使える。画面は32桁*4行。メモリーは標準32キロバイト。  この中の同じアルファベットのグループに相手の機種があれば、移植は比較 的楽なはずです。それでは移植のときに注意する点を一つづつみていきましょ う。 2.2 メモリー  当然の事ながら、プログラムをポケコンに実行させるには、メモリーにいれ なければなりません。ところが、場合によってはプログラムが大きすぎてメモ リーに入らないことがあります。特に移植の場合には、元のプログラムの容量 と移植したプログラムの容量が違うために、メモリーにはいるか入らないかわ からないことが多いと思います。この際に、まず相手の機種の容量よりも自分 の機種のメモリー容量の方が小さいときは、だいたいそのままでは移植できま せんので、不必要なところを削ったり、移植を諦めるしかありません。そうで なくても、機種によってプログラムの記憶の仕方が違うためにプログラムを削 らなければならないこともあります。これは実例ですがPC−1350で19 KBのプログラムをPC−1600Kに移植すると22KB、PC−E500 に移植したら28KBにもなってしまいました。 2.3 特殊な命令  機種によっては、その機種にある特別な機能(数式記憶とかデーターベース とか)を使うための命令がBASICにあることがあります。もし、移植しよ うとするプログラムがその様な命令を使っているときは、まずその機能を使わ なくても実行できるかどうかを検討します。  例えば、PC−E500シリーズにはAER命令というのがあります。これ は数式記憶機能に記憶された数式を関数とみて実行するものです。もし、この AERがプログラムに使われているときは次のようにします。AER命令が現 れたら、すべて元の数式に置き換えるか、GOSUBで数式の入っているサブ ルーチンをコールします。(変数の変換などが必要です。)こうしておけば、 数式記憶を使わなくてもプログラムの実行ができるわけです。  C系の機械(先ほどのグループわけでC1,C2,...となっているもの。 以下同様。)では、ほかの機種にない数学関数が使われていたりします。この ようなときも、定義式を使うなり、ほかの関数で近似してしまえば良いのです。 (PC−9801のBASICリファレンス・マニュアルにこのようなものが たくさん載っています) 例: HSN(X)=(EXP(X)-EXP(-X))/2  また、RND関数がない機械では、適当な乱数を作る式を使えば良いのです。 PC−1211付属のプログラムライブラリには計算によって疑似乱数を発生 するプログラムが載っています。(PC−1246DBシリーズの場合、いろ いろな関数を使ったプログラムの移植はほぼ絶望とみた方が良いかも知れませ ん。) 2.4 変数  シャープの初期のポケコン(A1、A2グループ)や低価格ポケコン(A4 グループ)では、2文字の変数が使えませんので注意が必要です。というのも これらの機種では、掛算の省略を許しているからです。例えばABというのが あった場合、これら以外の機種では変数ABとして扱われるのに対して、これ らではA*Bとして扱われます。またカシオのポケコンでもK1からK3グルー プの機種では2文字の変数は使えません。  もし、元のプログラムに2文字の変数があったときは、これらの2文字の変 数が使えない機種では、1文字の変数に置き換えなければなりません。また逆 に、掛算の省略が行われていたときには、ほかの機種では掛算記号”*”を間 にいれなければなりません。また、K6グループではかなの変数が使えますの で、移植の際に元のプログラムにかなの変数が使われていたときは、アルファ ベットの変数に置き換える必要があります。  文字型変数の場合はさらに注意が必要です。まず、シャープの場合C6、C 7グループ・Dグループを除きアルファベット1文字の変数には7文字、2文 字の変数では15文字しかいれることができません。またDグループでは1文 字、2文字に関わらず15文字までです。従って、Dグループで1文字の変数 が使われていたときでも、ほかの機種に移植のときには、2文字の変数か15 文字の文字型配列を使う必要があります。  C6、C7グループでは、文字数の制限はなく255文字まで自由に使える ので、ほかの機種でこの文字数制限を活用したプログラムがうまく動かないこ とがあります。その際には、文字関数を使って、文字数を制限したりする必要 があります(LEFT$(A$,7)など)。また逆にC6、C7グループで 80文字以上の文字列を変数に代入するプログラムをほかの機種に移植するこ とは困難です。これは、ほかの機種では、一番文字数を多く取れる文字型配列 変数を使っても最大80バイトの文字列しか作れないからです。  また、C6、C7グループではSTR$関数で得られる文字列の頭にスペー スが追加されるのでSTR$関数を使ったプログラムを移植するときには注意 して下さい。場合によってはスペースを取り除くことも必要です。これには次 のようにします。 RIGHT$ (STR$ (A),LEN STR$ (A)-1)  次に、カシオの場合、K1からK3グループまでは、文字関数は$という特 別な変数に対してしか使うことができませんので注意が必要です。これに対応 して、これらの機種では関数の形がほかの機種と異なっています。(例えばM ID$がMIDになっている)  数値変数で注意するのは、C5、C7グループで使うことができる倍精度変 数です。もし、倍精度変数が使われた場合、単精度の変数に直す必要がありま す。(当然のことだが精度は落ちる)このとき、すでに使われている単精度変 数と名前が重ならないようにしなければなりません。  大部分のポケコン(A1からC5、K1からK3グループ)では、同じ名前 の数値変数と文字変数を同時に使うことができませんので、これ以外の機種か ら移植するときは、名前が重なっていないかどうかを注意する必要があります。 (配列変数の場合は関係ありません)  配列変数では、余り注意することはありません。但し、A1からC5までの 機種では、1文字変数AからZ、およびA$からZ$をA(1)からA(26)、 A$(1)からA$(26)として扱うことができますが、K1からK3の機 種ではこれらに加えて、ZをA(26)とかE(21)とかに表すことができ ます。また、Dグループでは、@(1)から@(26)、および@$(1)か ら@$(26)として扱うことができます。よって、これらの異なった表現を 持つ機種の間で移植するときは表現の違いに注意しなければなりません。また C6、C7ではこのような表現はありませんので全てを普通の配列にするか、 または普通の変数名に変える必要があります。A1からC5までの機種でA (27)以上の変数がDIM宣言なしで使われていたときも同様です。 2.5 キャラクタの違い  機種によっては、プログラム中に出て来る文字に違いがあることがあります。 まず、プログラム中に(ダブルクォーテーションに囲まれていないところ)自 分の持っている機種で使われていないキャラクタが出てきたときの対処法を挙 げます。  A1とA2およびA4の機種のプログラムでは、数値の指数表示にE(縦の 線が太い)が使われていることがあります。これらは、ほかの機種ではE(普通 のアルファベット)にするだけで結構です。ただし、E5のような指定があっ たときはE5ではなく1E5にしなければなりません。また、A1からC5及 び、PC−1500シリーズでは、√やπが使われていることがありますので、 ほかの機種ではPIやSQRに変更する必要があります。(PC−1600K では[と]でもよい)カシオの機械では、不等号記号≦や≧または≠が使われ ますが、これらをシャープのマシンに移植する際には、<=、>=、<>に変 更する必要があります。  次に、CHR$関数を使っている場合には、CHR$関数で使われている文字コードがどうなっているかを調べる必要があります。もし、コードが異なっていたときには自分の機種に合わせてコードを変更しなければなりません。  ダブルクォーテーションで囲まれたところに自分の機種の持っていないキャ ラクタが出てきたときは、いろいろな方法がありますが、一つ目は自分の機種 にあるもっとも近いキャラクタを使うことです。この際、CHR$でその文字 をチェックしていることがあるので、その部分も書き換えなければならないこ ともあります。次に考えられるのは、そのキャラクタをグラフィックスとして 表示させることです。グラフィックスの移植については後で述べます。なお、 このときCHR$でその文字列をチェックしていた場合には全く新しくチェッ ク部分を作り替えなければなりません。 2.6 予約語の違い  機種によっては、同じ事をする命令でも名前が異なっている場合があります。 例えば、PC−1500ではLINEはプリンタに線を書く命令ですが、これ と同じ命令は、ほかの機種ではLLINEとなっています。このように、同じ 名前の命令でも自分の持っている機種では、元のプログラムとは違った働きを することがあるので注意して下さい。また、自分の持っている機種にその命令 がなくても、同じ働きをする命令に置き換えれば良いのです。このような例を 挙げてみましょう。 a)PC−1500とPC−1600 LINE LLINE LCURSOR TAB CALL XCALL POKE/PEEK XPOKE/XPEEK b)シャープ従来機とC6、C7グループ CURSOR LOCATE MEM FRE c)A,B,CグループとPC−1600 SAVEM/LOADM BSAVE/BLOAD CROTATE ROTATE d)カシオとシャープ PRINT CSR CURSOR/LOCATE e)K2グループ初期とその他 CLEAR NEW VAC CLEAR 2.7 画面表示  ポケコンの画面の大きさは機種によって違います。それでは、移植元の機種 と自分のポケコンとの画面の大きさが違っていたときにはどうしたら良いでしょ う。まず、自分の機種の方が画面が大きいときには、特に変更する必要はあり ません。ただし、シャープの機種ではWAIT文の初期値が、1行の機種では 無指定(ENTERが押されるまで待つ)なのに対して、2行以上の機種では 初期値は0になっているので注意が必要です。つぎに、自分の機種の方が画面 が小さいときには、表示を何度かに分けてるか、あるいは表示を少し削るかす る必要があります。また、カシオのマシンでは、PRINT文が一度に表示し きれないときに、横スクロールしながら表示する機能があります。これをシャー プのマシンに移植するときは、何度かに分けて表示させるか、横スクロールす るプログラムを作る必要があるでしょう。  CURSOR/LOCATE文の無い機種にそれらの命令を使ったプログラ ムを移植するには多少工夫が必要です。まず1つめの方法は、画面の一桁一桁 を文字変数一文字ずつに割り当てるやり方です。これはPC−1211の頃よ く行われたやり方です。例えば、 CURSOR 5:PRINT "A"  というような命令があったときに A$(5)="A":PRINT A$(0);A$(1);A$(2);A$(3);A$(4);A$(5);………  というように置き換えるわけです。(当然のことながらほかの配列にはその 桁の表示内容を表す文字が入っている)但し、この方法で数値変数の値を表示 させることはかなり困難です。またもう1つの方法は、画面全体を1つの文字 変数にする方法です。この方法では、先ほどの例は次のようになるはずです。 (あらかじめA$(0)を画面の桁数の長さの文字配列と宣言しておく。) A$(0)=LEFT$(A$(0),5)+"A"+RIGHT$(A$(0),24-6):PRINT A$(0)  この方法ですと、数値の表示も比較的楽にできます。 2.8 グラフィックス  グラフィックの方法は機種によって全く異なりますので、ここでは代表的な 機種(実は私が持っている機種だけだったりして)でのグラフィックの方法を 述べることとします。 A1、A4、C2、K1、K2、K3グループ  グラフィックの方法はありません。もし、グラフィックを使ったプログラム を移植するなら、使わないように変更するか、諦めるしかないでしょう。 A2グループ  これらの機種にはグラフィク命令がありません。従ってグラフィックを表示 させるにはV−RAM(表示用のメモリー)に直接書き込む必要があります。 VRAMの構造は次のようになっています。 1桁目 12桁目 13桁目 24桁目 +-----------------------+-----------------------+ | &F800〜&F83B| &F87B〜&F840| +-----------------------+-----------------------+  シンボルは&F83Cと&F83Dに入っています。ただし、後半の12桁 は逆順に並んでいます。また、PC−1245では17桁目から24桁目まで は表示されません。  ところが、A2グループでは通常V−RAMを計算時のワークエリアとして 使っており、計算中には画面にゴミのようなものが表示されます。そのために 普段は画面を表示しない状態になっていますので、このようにV−RAMに直 接書き込んでも画面には何も表示されません。そこであらかじめプログラム中 に次のように指定しておく必要があります。 CALL &11E0  この命令を実行することによって、表示をさせることができます。また、表 示を消すには CALL &11E5  をプログラム中にいれて置いて下さい。ちなみに、PRINT ””でV− RAMをクリアできます。 A3グループ  これらの機種にもグラフィック命令がありませんので、V−RAMに直接書 き込む必要があります。V−RAMの構成は次のようになっています。 1桁目  12桁目 13桁目 24桁目 +-----------------------+-----------------------+ 1行目 | &2000〜&203B| &2800〜&283B| +-----------------------+-----------------------+ 2行目 | &2040〜&207B| &2840〜&287B| +-----------------------+-----------------------+  A2グループと違って、特にCALL文などを使う必要はありません。 B1、B2、C7グループ  これらの機種にはグラフィック命令があるので、それを使って下さい。特に B2グループでは直接V−RAMをいじくることは困難になっています。また、 B1、B2では、キャラクタ座標とグラフィック座標が1文字分ずれているの で注意が必要です。 C1グループ  これらの機種でも、V−RAMに直接書き込む必要があります。V−RAM の構造は次の通りです。 1桁目 7桁目 8桁目 16桁目 +-----------------------+-----------------------+ | &6000〜&6027| &6067〜&6040| +-----------------------+-----------------------+  インジケータは&603C、&603D、&607Cに入っています。後半 8桁では、V−RAMの並び方が逆になっているので注意が必要です。しかし、 V−RAMに書き込んだだけでは、表示させることはできず、 CALL &5A2  を実行する必要があります。また、表示を消すには、 CALL &59E  を実行して下さい。 C3グループ  グラフィックはV−RAMに直接書き込んで下さい。 PC−1440の場合 1桁目 12桁目 13桁目 24桁目 +-----------------------+-----------------------+ | &6000〜&603B| &607B〜&6040| +-----------------------+-----------------------+ PC−1445の場合(何じゃこれは!?) 1桁目 5桁目 6桁目 8桁目 9桁目 10桁目 12桁目 +-------------+-------------+-------------+-------------+ | &6000→&6018| &602D→&603B| &6028→&602C| &6019→&6027| +-------------+-------------+-------------+-------------+ 13桁目 15桁目 16桁目 17桁目 19桁目 20桁目 24桁目 +-------------+-------------+-------------+-------------+ | &6067←&6059| &606C←&6068| &607B←&606D| &6058←&6040| +-------------+-------------+-------------+-------------+  シンボルはどちらも&603C、&603D、&607C、&607Dに入っ ています。但し、表示をさせるには、 CALL &538 (PC−1440の場合) CALL &563 (PC−1445の場合) 表示を消すには CALL &534 (PC−1440の場合) CALL &55F (PC−1445の場合)  を実行する必要があります。 C4グループ 例によってV−RAMに直接書き込みます。 PC−1450の場合 1桁目 12桁目 13桁目 16桁目 +-----------------------+-----------------------+ | &7000→&703B| &707B←&7068| +-----------------------+-----------------------+  シンボルは、&703C、&703D、&707Dに入っています。 PC−1460の場合 1桁目 6桁目 7桁目 9桁目 10桁目 12桁目 +-------------+-------------+-------------+ | &3000→&301D| &302D→&303B| &301E→&302C| +-------------+-------------+-------------+ 13桁目 15桁目 16桁目 18桁目 19桁目 24桁目 +-------------+-------------+-------------+ | &306C←&305E| &307B←&305D| &305D←&3040| +-------------+-------------+-------------+  シンボルは、&303C、&303D、&307Cに入っています。  さて、V−RAMに書き込んだら次のようにして表示させます。 CALL &5A0 (PC−1450) CALL &4B8 (PC−1460) 表示を消すときは次のようにします。 CALL &59C (PC−1450) CALL &4B4 (PC−1460) C5グループ  グラフィックにはGPRINT命令があります。ただし、このGPRINT 命令はLCDの1桁分づつしか表示できません。また、V−RAMに直接書き 込むこともでき、その構成は次のようになっています。 1桁目  12桁目 13桁目 24桁目 +-----------------------+-----------------------+ 1行目 | &2800〜&283B| &2A00〜&2A3B| +-----------------------+-----------------------+ 2行目 | &2840〜&287B| &2A40〜&2A7B| +-----------------------+-----------------------+  シンボルは、&283C、&283D、&287C、&287Dに入ってい ます。また、特にCALL文などを実行する必要はありません。詳しくはポケ コンうらわざ大事典partIをみて下さい。 C6グループ  グラフィック命令がないので、直接V−RAMをアクセスしなければなりま せん。(私もこれ以上のことは知らない) C7グループ  素直にグラフィック命令を使いましょう。V−RAMはLCDコントローラ を通してしかアクセスすることはできません。(どうしても直接V−RAMを アクセスしたい人は第1部・第4章参照) Dグループ  グラフィック命令があるのでそれを使って下さい。ただし、PC−1600 のGPRINT命令は、座標の指定が左上の点を指定するようになっているの で注意して下さい。(ほかの機種では左下を指定する)また、仮想V−RAM (ただし、PC−1600では4行目のみ)に書き込むこともできます。 2.9 その他  シャープの初期の機種と後期の機種ではFOR NEXT文の構造が異なっ ています。A1、A2、A4、Dグループでは、32767以上の数を使うこ とができず、またSTEPで小数を指定することもできません。また、ループ を抜けたときの変数の値も違っています。  そのほかにA1、A2、A4グループでは行番号が999までしか使えない ので注意が必要です。(気が付くと行番号を作れないなど)  C6、C7グループでは論理式の返す値が0と−1ですので(ほかの機種で は0と1)論理式を使っているときには符号を反対にする必要があります。  最後に、機種によって実行時間が違うことも注意する必要があります。よっ て、もし、速すぎるときにはダミーループをはさんだりして、スピードを遅く することも必要です。 2.10 マシン語のプログラムの場合  マシン語のプログラムの場合は、移植は非常に困難です。もし、CPUが違っ ていれば、全く違ったマシン語を使っているわけですし、たとえ同じでも機械 の内部構造が違っていたりするためです。移植するよりも新しく作った方がよ いでしょう。また、アルゴリズムだけを使う手もあります。このとき、相手の 機種でROM内ルーチンを使っているときには、それが何をするものであるか 知っておく必要があります。(まあその機種のユーザーでもなければ判らない でしょうが。) 2.11 移植の実際  ここまでみてきて、移植するのは大変だと感じた人もいるでしょう。しかし、 実際にはそんなに複雑なことはありません。私の場合、PC−1350からP C−E500の移植がほとんどですが、それほど苦労もなく移植できます。ま た、これらの移植テクニックを知っておくことは、プログラムを自分が作ると きにも役立つことでしょう。 第3章 プログラムを打ち込む  ポケコンにはマイコンなどと違って、いわゆる市販ソフトというのがほとん どありません。そのかわり「ソフトウェア・ライブラリ」というのがあって、 結構実用になるソフトが多数掲載れています。また最近ではPJ(ポケコン・ ジャーナル)という便利な雑誌もあるので、べつに自分でプログラムを作らな くてもただプログラムリストを打ち込むだけでゲームなどができるようになっ ています。しかし、プログラムを打ち込むだけなのにもかかわらず、結構苦労 している人が多いようです。さて、この章ではいかに速く、正確にプログラム を打ち込むかをテーマにしていきます。 3.1 一本指打法はやめよう  皆さんは、プログラムを打ち込むときに、まさか人差指一本でやっているの ではないでしょうか。これでは時間がかかるのも当然です。とにかく両手の指 を全部使うぐらいの気持ちで打ち込むとかなり時間が省略できます。キーが小 さいですから、タイプライターのようにはできませんが一本で打つよりもまし でしょう。ちなみに、私の場合、BASICのプログラムは右手の指を全部つ かって、マシン語のプログラムの場合は両手をフルに使って打ち込んでいます。 例えば、これはマイコンの場合ですが、BASICのプログラムなら1時間に 最低2ページ(ASCII誌のリストの場合)、マシン語の場合ならば6キロ バイトを1時間で打ち込むことができます。ポケコンの場合はキーの大きさの 関係で少し遅くなりますが、まあまあの速さでしょう。 3.2 省略形を知れ シャープのポケコンには省略形という便利なものがあります。これを使えば、 PRINTと6文字も打つ代わりにP.とするだけで良いのです。省略形は、 基本的にほかの命令と間違われないぐらいの長さだけ書いたものに”.”をつ けたものです。これはマニュアルの後ろにも省略形一覧というものが書いてあ りますから、ぜひ覚えておいた方がよいでしょう。ただし、機種によって省略 形が違うことがあるので(例えばPA.はPC−1211ではPAUSEだが、 PC−1251ではPASSになる)、たくさんのポケコンを持っている人は 注意して下さい。(そんな人いないか。)ただし、省略形を使いすぎると次の ような場合があるので注意しましょう。 10:IF S>H THEN H=S ELSE 20 このようなプログラムがあったときに、次のように打ち込んだとします。 10 IFS>HT.H=SEL.20 さて、BASICにはどの様に解釈されたでしょうか。確かにT.はTHE Nの省略形ですし、EL.はELSEの省略形です。(PC−E200/E5 00系の場合) 10:IF S>HTN H=SEL0.2 おかしな解釈がされたようです。実は、HT.の部分はHTNの省略形と解 釈されてしまったのです。また、EL.20のELの部分は、前と一続きのS ELという変数として解釈され、よって.20の部分が0.2となっているわ けです。 このように省略形を使うときにはポケコンがどの様に解釈するかを考える必要 があります。もし、誤った解釈をされるようだったら、そこの部分は省略形を 使わないようにしましょう。またPC−E500シリーズならば命令の間にス ペースをいれることによってこのようなことを避けることができます。 3.3 エデット機能を使いこなせ  さて、BASICのプログラムを打っていて、同じような文が出てきたとき にどうしますか。こんなときに、もう一度最初から打ち込むのは無駄と言うも のです。こんなときは、BASICのスクリーンエディット機能を使って、行 番号と、異なっている部分を変えるだけでよいのです。これだけに限りません が、最近のポケコンのBASICのエディタには結構いろいろ機能があるので、 きちんとマニュアルを呼んでマスターしておくと良いでしょう。 3.4 優秀なモニタを手にいれよう  BASICのプログラムと違って、マシン語のプログラムを打ち込むときに は、モニタと呼ばれる特別のプログラムを使わなければなりません。これはP C−E200などをのぞいては、自分で用意しなければなりません。ポケコン・ ジャーナルをみるとたいていのポケコンのモニタが発表されていますから、こ れを使うのがよいでしょう。  さて、マシン語のプログラムを打ち込むときには、モニタのできによって打 ち込む速さが断然違います。従って、優秀なモニタを手にいれる必要がありま す。優秀なモニタとは、次の条件を満たしていなければなりません。1つめは、 人間の打ち込む速度よりもモニタの動作スピードのほうが速いことです。これ は当然のことですが、BASICで作られたモニタの場合こうは行きません。 2つめは、余分な動作をしないことです。例えば、間違えて関係のないキーを 押してしまったときに変な動作をしたり、モニタの応答が速すぎて、余分にキー を押したことになってしまったりするようなことがないことです。3つめは、 簡単に使えることです。説明をみなければ使えないような複雑なモニタとか、 リロケータを使わなければ、アドレスを変更できないリロケータブルでないモ ニタは失格だということです。この点でPC−1470U用のMonitor −70Uは失格だと思います。(ほかにモニタがないのでしかたないが。まあ、 リロケータがヘッダとして一体化できるようになったからよしとしよう。) 第4章 昆虫採集をしよう  さて、どうにかしてプログラムを作ったり、移植したり、打ち込んだとしま す。しかし、打ち込んだプログラムが一度で動くのは希で、エラーが起きたり、 変な動作をしたり、暴走したりするのが普通です。この章ではそんなときの対 処法を述べていきます。 4.1 エラーコードの読み方  BASICでは、実行できない命令に出会ったときにエラーを発生します。 エラーが出る場合の対処法は比較的に楽です。ここでは、それぞれのエラーに ついて、その傾向と対策をみていきます。 a)PC−1211  PC−1211では、エラーは番号で返されます。エラーの種類は6つしか ありません。 1:文法エラー・演算エラー・メモリー指定エラー  このエラーは、一般的には命令を打ち間違えたか、またはPC−1211に ない命令を使ったかのどちらかです。よって、きちんと打ち直せば治る場合が ほとんどです。しかし、誤りが見つからないときは、文法エラーではありませ ん。そのときは、変数の値をチェックしてみて下さい。案外0で割っていると か、数値変数のはずが、文字変数になっていたりするものです。 2:ラインエラー  GOTO文などで行番号がないときに発生します。おそらく、行番号を打ち 間違えたか、飛び先の行をいれ忘れたかのどちらかでしょう。 3:深みエラー  FORループ、またはGOSUBの深みが4段を越えたときに発生します。 FORの時はFORとNEXTの変数があっているかを調べて下さい。また、 FORループからGOTO文で飛び出しているときにも発生することがありま す。GOSUBの場合は、おそらくGOTOとGOSUBを打ち間違えたので しょう。 4:ステップオーバーエラー  メモリー不足の時に発生します。プログラム実行中に出るとしたら、おそら くA()で指定したメモリーが実際に使用する範囲に入っていないものと思わ れます。直接指定の場合は、完全なメモリー不足ですから、プログラムを削る しかないでしょう。間接指定の場合は、間接指定に使っている変数の動きをチェッ クしてみましょう。 5:磁気テープ制御エラー  プログラム実行時に出ることはないでしょう。 6:フォーマットエラー  USINGで指定したフォーマットで表示ができないときに発生します。ま ず、USINGの指定をチェックします。もし、正しければ表示する変数の動 きを追ってみて下さい。 b)PC−1251からPC−1470Uまで  これらの機種ではエラーコードはすべて共通で、番号で返されます。 1:文法エラー  単なる打ち間違いか、その機種にない命令を使おうとしたのでしょう。ちゃ んと打ち直せば終わりです。 2:演算エラー  0で割ったりしたとか、関数の扱う数の範囲を越えていたときに発生します。 その演算で使われている変数をチェックしてみて下さい。 3:DIMエラー、範囲制限エラー  2度同じ配列を宣言したとか、配列で宣言した範囲を越えて使っている時に 発生します。前者の場合は、おそらくDIM文の変数を間違えたか、GOTO 文の行番号を打ち間違えたものと思われます。また、DEFキーで実行を開始 したときにプログラムに間違いがなくても発生することがあります。このよう なときには、DIMの前にCLEARをいれておけば良いでしょう。ただし、 この場合にはほかの変数も消去されてしまいます。後者の場合には、まずDI M文で指定する範囲があっているかを確かめます。もし、正しかったときには、 配列の添え字をチェックしてみましょう。 4:ラインエラー  GOTO文などで行番号がないときに発生します。おそらく、行番号を打ち 間違えたか、飛び先の行をいれ忘れたかのどちらかでしょう。 5:深みエラー  FORループ、またはGOSUBの深みが指定された数を越えたとき、およ び、FORがないのにNEXTが使われたりGOSUBがないのにRETUR Nが使われたりしたときにも発生します。FORの時はFORとNEXTの変 数があっているかを調べて下さい。また、FORループからGOTO文で飛び 出しているときにも発生することがあります。GOSUBの場合は、おそらく GOTOとGOSUBを打ち間違えたのでしょう。また、文字列を演算すると きに、80文字を越えたときにも発生します。使われている変数を追ってみて 下さい。 6:容量オーバー  メモリー不足の時に発生します。プログラム実行中に出るとしたら、おそら く配列を指定したときにメモリーが取れないのでしょう。配列の範囲をチェッ クしてみましょう。どうしようもないときは、プログラムを削るしかないでしょ う。 7:フォーマットエラー  USINGで指定したフォーマットで表示ができないときに発生します。ま ず、USINGの指定をチェックします。もし、正しければ表示する変数の動 きを追ってみて下さい。 8:入出力エラー  このエラーが発生するときは、おそらくプログラムに責任はありません。指 定された周辺機器がちゃんと接続されているか、また電源が入っているかを確 かめて下さい。 9:その他のエラー  何か原因があるはずです、良く考えましょう。(滅多にでませんが。) c)PC−E500シリーズ  この機種では、エラーはメッセージとして表示されます。今までの機種に比 べて、きめが細かくなっています。 10:Syntax error  文法エラーです。単なる打ち間違いか、PC−E500シリーズにない命令 を実行しようとしたのでしょう。 11:Direct command error  ダイレクト実行しかできない命令をプログラム中で使おうとしたときに発生 します。マニュアルを良くみて、使っている命令がプログラム実行できるかど うかを調べてみてください。 12:Mode error  プログラム中で発生するとしたら、OPEN文でモードの指定を間違えたの でしょう。モードの指定があっているかどうか確認して下さい。また、”PR N:”,”SCRN:”にはINPUTが指定できませんし、”KYBD:” にはINPUTしか指定できないのでそれもチェックして下さい。 20:Over flow 21:Division by Zero 22:Illegal function call  おかしな演算をしたときに発生します。その演算で使われている変数の値を チェックしてみて下さい。 30:Duplicate Definition 31:Array specified without DIM 32:Subscript out of range  DIM文での指定がおかしいか、または、実際に配列変数を使うときの添え 字の指定がおかしいかのどちらかでしょう。その配列変数が、きちんとDIM で宣言されているか、添え字の範囲がおかしくないかチェックしてみましょう。 場合によっては、GOTO文の飛び先行番号が間違えていて、DIM文を2回 実行してしまっていることもあるかも知れません。 33:Data out of range  BASIC命令の値の範囲が規定外のときに発生します。これも一般的には、 変数の値をチェックすれば良いでしょう。 40:Undefined line 41:Illegal line number  GOTO文や、GOSUB文で指定した行が存在していないときに発生しま す。行番号、またはラベルの打ち間違いか、プログラムを打ち込むときに一行 飛ばしてしまったかのどちらかでしょう。 50:GOSUB or FOR nesting error  GOSUBやFORのネストの段数がBASICで扱うことのできる数を越 えたときに発生します。GOTOをGOSUBと打ち間違えていないか、また は、FORループ中から飛び出していないかをチェックして下さい。 51:RETURN without GOSUB  GOSUBで呼び出されていないのにRETURNに出会ったときに発生し ます。GOSUBをGOTOと打ち間違えていないかチェックしてみて下さい。 52:NEXT without FOR  FORとNEXTのループに食い違いがあったときに発生します。一般には、 FORとNEXTの変数が同じものかどうかを調べれば良いでしょう。 53:Out of data  READ文を実行したときに、それに対応するDATAが存在しないときに 発生します。READ文で読み込む回数が正しいかどうか、または、DATA 文中で、カンマ”,”とピリオド”.”を間違えていないかどうかを調べて下 さい。 55:String too long  文字列を演算する際に254文字を越えたときに発生します。その演算で使 用されている変数がどこかで、おかしくなっているのでしょう。どうしようも ないときは、あらかじめMID$などで、演算結果が254文字以内になるよ うに調整して下さい。 57:RESUME without error  ON ERROR文の処理実行中でないときにRESUMEが使われたとき に発生します。おそらくは、GOTO文の行番号の打ち間違いでしょう。 60:Out of memory  メモリー不足です。プログラムを削ったり、配列変数を削ったりする事も必 要でしょう。どうしても回避できないときは、RAMカードを買いましょう!? 70:Can't print in specified format 71:USING format error  USING文のフォーマット指定がおかしいか、表示するときの変数の値が おかしいかのどちらかでしょう。 72:I/O error  存在しない周辺機器を使おうとしたときに発生します。周辺機器がきちんと 接続されているか、電源が入っていてるかどうか確かめて下さい。 73:Too many files open 同時にオープンしているファイルの数が多すぎます。一般的には、3つ以上 のファイルを同時にオープンすることは少ないでしょうから、同じファイル番 号をいくつかのファイルで共用したり、または使っていないファイルを一時的 にクローズすると良いでしょう。 74:NAME error  NAME文で指定したファイル名がおかしいときに発生します。ドライブを 越えて名前を指定している場合がほとんどです。(NAME "E:123" AS "X:456" のように) 75:Bad drive name  装置名の指定がおかしいときに発生します。ファイル名をチェックしてみて ください。 76:File write protected  ファイルが書き込み禁止状態になっています。本当にそのファイルの内容を 変更しても良いのなら、ライトプロテクト属性を解除してください。 77:Disk full  ディスクの容量がいっぱいです。新しいディスクに交換しましょう。 80:Tape read error 82:Verify error  テープの読み込みに失敗しました。データやプログラムの記録が消えてしまっ たのでしょう。(これは、プログラムの責任ではないな。) 84:Printer error  プリンタが接続されていない、または電源が入っていません。(このぐらい すぐわかるだろうに。) 85:File not open  ファイルをオープンしないで使おうとしたときに発生します。ファイル番号 が正しいかどうか確かめて下さい。 86:File already open  そのファイル番号のファイルがすでにオープンされているときに発生します。 ファイル番号が正しいかどうか、また以前使われていたファイルがきちんとク ローズされているかを調べて下さい。 87:Input past end  ファイルの最後をすぎて、データを読み込もうとしたときに発生します。読 み込むデータの数が正しいかどうか、または、ファイルの終わりをちゃんと検 出しているかどうかチェックして下さい。 90:Type mismatch  文字列変数に数値を代入した、または数値変数に文字列を代入しようとした ときに発生します。単なる打ち間違いか、文字関数の使い方が正しいかどうか を確かめて下さい。 94:File not found 95:Bad file name  ファイルが存在しない、またはファイル名がおかしいときに発生します。ま ず、指定したいファイルが本当に存在しているかどうかを調べて下さい。存在 していてこのエラーが発生したときには、ファイル名の指定が正しいかどうか を調べて下さい。 13:Can't continue 14:Program not exist 44:Bad line number 54:Buffer space exceeded 56:Line buffer overflow 92:Password mismatch 93:Invisible program  これらが、プログラム実行中に発生することはまずないでしょう。 d)PC−1500/1600  PC−1500/1600では、エラーはエラーコードで返されます。しか し、エラーの種類は非常に多いので、きめ細かな対応ができます。なお、10 0番以上のエラーはPC−1600のみ存在します。 1:Syntax error/Mode error(RUN/PRO) 26:Mode error(MODE0/1) 27:Function not available 73:Mode error(GRAPH/TEXT) 158:File mode error  文法エラーです。単なる打ち間違いか、その機種にない命令を実行しようと したとき、そのモードでは使えない命令を実行しようとしたときに発生します。 プログラムを良く見直して下さい。 2:RETURN without GOSUB/NEXT without FOR  GOSUBで呼び出されていないのにRETURNに出会ったとき、または、 FORとNEXTのループに食い違いがあったときに発生します。GOSUB をGOTOと打ち間違えていないか、FORとNEXTの変数が同じものかど うかを調べれば良いでしょう。 4:Out of data  READ文を実行したときに、それに対応するDATAが存在しないときに 発生します。READ文で読み込む回数が正しいかどうか、または、DATA 文中で、カンマ”,”とピリオド”.”を間違えていないかどうかを調べて下 さい。 5:Duplicate Definition 6:Array specified without DIM 8:Dimension over 2 9:Subscript out of range  DIM文での指定がおかしいか、または、実際に配列変数を使うときの添え 字の指定がおかしいかのどちらかでしょう。その配列変数が、きちんとDIM で宣言されているか、添え字の範囲がおかしくないかチェックしてみましょう。 場合によっては、GOTO文の飛び先行番号が間違えていて、DIM文を2回 実行してしまっていることもあるかも知れません。 7:Type mismatch 17:Data type mismatch 131:String with sign  文字列変数に数値を代入したり数値のような計算を行ったとき、または数値 変数に文字列を代入しようとしたときに発生します。単なる打ち間違いか、文 字関数の使い方が正しいかどうかを確かめて下さい。 10:Out of memory(変数指定時) 13:Out of memory(プログラム入力時) 22:Out of memory(プログラム読み込み時) 42:Out of memory(テープからの読み込み時)  メモリー不足です。プログラムを削ったり、配列変数を削ったりする事も必 要でしょう。どうしても回避できないときは、RAMモジュールを買いましょ う!? 11:Undefined line  GOTO文や、GOSUB文で指定した行が存在していないときに発生しま す。行番号、またはラベルの打ち間違いか、プログラムを打ち込むときに一行 飛ばしてしまったかのどちらかでしょう。 12:USING format error 36:Can't print in specified format  USING文のフォーマット指定がおかしいか、表示するときの変数の値が おかしいかのどちらかでしょう。 14:FOR nesting error/Buffer space exceeded 15:GOSUB nesting error/String too long  GOSUBやFORのネストの段数がBASICで扱うことのできる数を越 えたときに発生します。GOTOをGOSUBと打ち間違えていないか、また は、FORループ中から飛び出していないかをチェックして下さい。また、こ のエラーは文字列を演算する際に80文字を越えたときにも発生します。その 演算で使用されている変数がどこかで、おかしくなっているのでしょう。どう しようもないときは、あらかじめMID$などで、演算結果が80文字以内に なるように調整して下さい。 16:Over flow(データ)  数値の範囲が、10E99または&FFFFを越えています。単なる打ち間 違いでしょう。 18:Data number error 19:Data out of range  BASIC命令の値の数、または値の範囲が規定外のときに発生します。一 般的には、その命令が取るパラメータの数、その命令で使われている変数の値 をチェックすれば良いでしょう。 20:Fixed variable specify error  固定変数を@で間接指定するときに、かっこを忘れています。 21:Illegal function call ?  変数でなければならないところが、数式になっています。一度数式の値を別 の変数に代入するようにプログラムを変更して下さい。 23:Time setting error  時間の設定の方法が間違っています。PC−1600では、TIME=0の 指定ができないので注意が必要です。 28:Not string  文字列に命令や関数のコードを代入しようとしたときに発生します。これは、 プログラムのミスではなく、操作上のミスである場合がほとんどです。 32:Can't print  INPUT命令で、入力した内容を表示する場所がありません。GCURS ORで、ちゃんと表示できるように指定しなおして下さい。 34:???  マニュアルにも書いていないエラーです。一体どうやれば出るのか試してみ て下さい。 35:Periferal not available  使用されるべき周辺機器が接続されていません。きちんと接続されているか どうか確かめて下さい。 37:Over flow(計算時) 38:Division by Zero 39:Illegal function call  おかしな演算をしたときに発生します。その演算で使われている変数の値を チェックしてみて下さい。 43:Verify error/Data type mismatch  テープの読み込みに失敗したか、または記録された変数とそれを読み込む変 数の型が違っているときに発生します。読み込むデータの型や数が正しいかど うか確かめて下さい。 70:Pen move out of range 71:Line feed out of range 72:TAB error  これ以上ペンを移動できないときに発生します。LINE、LF、TAB命 令の取る値が正しいかどうか確かめて下さい。 74:LINE error LLINE/RLINEでの座標の数が多すぎます。 76:Can't lprint  LPRINT命令で、結果が表示できません。文字サイズを小さくするか、 印字幅を大きくして下さい。 78:Printer locked 79:Color error 80:Printer low battery  プリンタが動作できません。プリンタをチェックしてみてください。 104:Interrupt declaration over 9  ソフトウェア割り込みの数が9を越えています。使わない割り込みを解除し ましょう。 105:Interrupt nesting error  割り込み処理中に別の割り込みがかかったりして、処理能力をオーバーした ときに発生します。割り込み処理中にはほかの割り込みを禁止しておくと良い でしょう。 106:RETI without interrupt 107:RESUME without error  割り込み処理実行中でないときにRETIが現れたり、エラー処理実行中で ないときにRESUMEが使われたときに発生します。おそらくは、GOTO 文の行番号の打ち間違いでしょう。 150:Too many files open 同時にオープンしているファイルの数が多すぎます。一般的には、3つ以上 のファイルを同時にオープンすることは少ないでしょうから、同じファイル番 号をいくつかのファイルで共用したり、または使っていないファイルを一時的 にクローズすると良いでしょう。 151:File already existed  NAME文で指定した変更先ファイルがすでに存在しています。変更先のファ イルが本当に必要ないのならばあらかじめ削除するようにしましょう。 152:File not found 157:Bad file name  ファイルが存在しない、またはファイル名がおかしいときに発生します。ま ず、指定したいファイルが本当に存在しているかどうかを調べて下さい。存在 していてこのエラーが発生したときには、ファイル名の指定が正しいかどうか を調べて下さい。 153:File not open  ファイルをオープンしないで使おうとしたときに発生します。ファイル番号 が正しいかどうか確かめて下さい。 154:File already open  そのファイル番号のファイルがすでにオープンされているときに発生します。 ファイル番号が正しいかどうか、また以前使われていたファイルがきちんとク ローズされているかを調べて下さい。 155:Bad drive name  装置名の指定がおかしいときに発生します。 156:SET error  SET命令で、設定する属性が間違っています。 159:File or disk write protected  ファイルまたはディスクが書き込み禁止状態になっています。 164:Disk full  ディスクの容量がいっぱいです。 165:Input past end  ファイルの最後をすぎて、データを読み込もうとしたときに発生します。読 み込むデータの数が正しいかどうか、または、ファイルの終わりをちゃんと検 出しているかどうかチェックして下さい。 160:Disk not inserted 161:Disk not initialized 163:Disk changed in using file 166:Can't use disk 167:Disk crash 168:Disk low battery  ディスクを正しく扱える状態にして下さい。 24:Program protected 25:NEW address error 30:Line number overflow 40:Function format error 44:Checksum error 100:Can't RENUM 101:Bad device name 102:Device not exist 103:RAM mode can't set 108:Password mismatch 110:Mode can't change 112:Line buffer overflow  これらのエラーがプログラム実行中に発生することはないでしょう。 4.2 変数を追いかけろ  さて、いままで10ページにもわたってエラーの傾向と対策をみてきたわけ ですが、これらを見てみると実はエラーというものは、発生した行以外に原因 があるものがほとんどです。こんなときに、エラーが発生するのに関係がある と思われる変数の変化を追いながら実行すると、すぐに原因がわかるときがあ ります。また、好運にもエラーは発生していないが、何か動作がおかしいとい うときにも有効です。たとえば次のプログラムは配列D(0)〜D(10)に 0から10までの値をいれて、それを画面に表示して確認するプログラム(の つもり)です。 10:DIM D(9) 20:FOR I=0 TO 10 30:D(1)=I 40:NEXT I 50:FOR I=0 TO I0 60:PRINT D(I) 70:NEXT I 80:END 実行結果(期待) 0. 1.   (途中省略) 10. 実行結果(実際) 0.  特にエラーは発生しませんでしたが、何かおかしいですね。11個の数が表 示されるはずなのに1個しか表示されていません。そこで、プログラムを見て みると60行にPRINT D(I)という文が見つかります。そこで、どう やら変数Iがおかしいようだと気づきます。ここで、50行のFOR文を見る と…あれ、Iの範囲が0からI0になっています。10と入れるべきところを I0としてしまったようです。それでは50行を修正してもう一度実行してみ ましょう。 実行結果 0. 10. 0.    (途中省略) Subscript out of range in 60  今度は10個の数字が表示されましたが、0、1、2、3、…とならなけれ ばならないところがなっていないようです。しかも最後にエラーがでるという おまけ付きです。まず、このエラーについては前節のエラー一覧表を見れば 「使用する配列の宣言がおかしくないかチェックしろ」とありますので、10 行を見るとDIM D(9)となっています。0から10までの配列を使うの ですからここはDIM D(10)が正解でしょう。次に表示される値がおか しいので、本当に配列D()に数値が代入されているかどうか確かめてみましょ う。 D(2) 0.  代入されていません。プログラムを見ると30行に配列に代入しているとこ ろが見つかります。ん!?D(1)=Iとなっています。これではきちんと値 が代入されるはずがありません。どうやらまたIと1を間違えたようです。  このように変数を追いかけることは、プログラムの間違いを探すのに有効な 武器となります。このほかの方法には、怪しい変数が操作された直後に、PR INT文などをプログラムの中にいれて、その変数の値を表示させる。または、 TRONでトレースモードにして、変数を操作した直後にブレークして、変数 の値を確かめるなどがあります。 4.3 マシン語のプログラム  マシン語のプログラムではBASICなどと違って間違いをしてもポケコン のほうから指摘されることはありません。それどころか最悪の場合暴走して、 自分自身を破壊したり、BASICに戻ってこなくなったりします。したがっ て、マシン語のプログラムのデバッグは非常に困難です。(マイコンなどでは デバッガといって、マシン語のプログラムの動作を確かめながら実行させるプ ログラムもあります。)  自分で作ったプログラムの場合、一番多いのはロジックミス、つまりプログ ラムの構造(アルゴリズム)に間違いがある場合です。したがって、本当にこ のような方法でいいのかをチェックしてみる必要があります。また、ハンドア センブルのときはアセンブルミスということもありますので、できればアセン ブラを使ってアセンブルするのがよいでしょう。 4.4 タイプミスに注意  先ほどのプログラムではIと1をわざとまちがえてプログラムを作ったので すが、実際にプログラムを打ち込むときにいちばん間違え易いのがIと1なの です。ポケコンのリストのように文字が荒いものだとよく考えてもどちらだか 判らないこともあります。Iと1のほかに間違え易いものとしては、0(零) と8(ポケコンのリストでは0に斜線が入るため)、0(零)とO(オー)、 数字の1とl(小文字のエル、タイプライターでは数字の1のキーがなく小文 字のエルで代用しているのもあるようです。)  マシン語のプログラムを打ち込むときには、一般にチェックサムというもの がついています。よって打ち間違いの大半は、このチェックサムが正しいかど うかを調べればわかります。しかし、チェックサムも万能ではありません。次 の例を見てください。 0000:01 23 45 67 89 AB CD EF:C0  これはダンプリストの一例です。いちばん右端がダンプリストです。ここで、 まちがえて次のように打ったとします。 0000:01 23 45 87 69 AB CD EF:C0 ~ ~ 波線をしたところが打ち間違えたところです。しかし、チェックサムは同じ 値になっています。このように1行に打ち間違いが2つ以上あったときには間 違いがわからないこともあります。 4.5 もう一度見直しを  さて、これまでの必死の努力によってバグが取れたとします。しかし、これ でプログラム中の全てのバグがなくなったといえるのでしょうか。実際には、 まだ発覚していないバグが潜んでいることがほとんどです。1万回正常に動い ても次の1回でバグが発見されることもあるのです。これらのバグを取り除く ために、最後にもう一度、全てのプログラムを見直して下さい。(それでも取 れないときは、バグであることをごまかすだけさ!「これはバグではない、仕 様である。」) 第4部 ポケコン解析入門  この第4部は本当はプログラム・ライブラリにするつもりでしたが、気が変 わったのでポケコンの解析の仕方を述べていくことにします。 第1章 ポケコン解析とは 1.1 ポケコン解析の目的  突然ですが、いまあなたが今日発売されたばかりのポケコンを持っていると します。さて、あなたはいますぐにプログラムを作ることができるでしょうか。 マニュアルを一通り読めばBASICならば大体のことはできるでしょうが、 マシン語のプログラムを作ることはできないでしょう。と言うのは、マニュア ルにはCPUの種類など書いてあることがほとんどないので、どのCPUのマ シン語を使って良いのかわからないことと、たとえCPUがわかっても、マシ ンの構造がわからないために画面に文字を書くことも、キー入力をすることも できないからです。  こんなときにポケコンの構造を調べるのがポケコン解析です。従って、これ はある程度の実力と、勘が必要となります。また、未知のものに対するわけで すから時間もかかります。でも、解析の結果は自分一人のプログラムに役に立 つだけではなく、同じポケコンを持つ全ユーザーの共通の財産となるわけです から、とても重要なものです。  ポケコンの解析の内容はだいたい4つぐらいに分けられます。 1.メモリー配置 2.BASIC 3.ハードウェア 4.CPU自体 メモリー配置はマシン語のプログラムをCPUに実行させるためにはぜひ知っ ておく必要がありますし、BASICの解析はROM内サブルーチンを使った りワークエリアを操作するときに必要です。またハードウェアの解析はマシン 語で文字を出力したいときなどに必要です。CPUの解析というのは、そのC PUが新しいものでマシン語が公表されていないときに行います。 1.2 解析に必要なもの  さてポケコンの解析にはどの様な道具が必要なのでしょうか。まあ場合にも よりますが少なくとも次のようなものを揃えておく必要があります。1つめは メモリーの内容を覗くために必要なメモリー・ダンプ・プログラムです。これ がなくては話になりません。次にCPUがわかっている場合には逆アセンブラ が必要です。その機種用の逆アセンブラが発表されていなくても、同じCPU をつかった機種の逆アセンブラが使えますし、そうでなくてもBASICなど で自作すれば良いのです。あとは回路図があると便利ですが大体のポケコンは ゲートアレイなどを使ってICの数を減らしていますのである程度の勘と知識 が必要です。  そのほかに解析をしていて気付いたこと、わかったことなどを記録しておく ものが必要でしょう。私の場合解析専用にノートを2冊持っています。あとは ほかの機種を参考にして解析を進めていくときに、解説書が必要なぐらいです。 必要な道具は必要に応じて作れば良いのです。 第2章 解析の実例 2.1 PC−1600K/E500/1251のBASIC内部コード  BASICを使っていてまず思うのはユーザーの入れたプログラムがメモリー にどう格納されるかでしょう。そんなときに内部コードを調べたりします。し かしBASICの内部コードを調べるのは単にBASICのテキストの格納の され方を知るだけではなく、BASICの命令を実行するサブルーチンのアド レスなどもわかるために、後々の解析の助けにもなります。またひょっとする と隠し命令を発見できるかも知れません。(実はこれが楽しみだったりする。)  さて、内部コードを調べるための道具ですが、これにはキャラクタも表示で きるダンププログラムがあれば十分です。  それではPC−1251から順番にみていきます。私の持っているPC−1 251はいわゆる00バージョン(PEEK &7FFF=0のもの)ですの で、ほかのものとはアドレスが違っているかも知れません。まずダンププログ ラムでROMの先頭アドレスである&4000からみていきます。すると&4 100あたりから意味のある文字列が現れてきます。(注:PC−1251の 内部コードはASCIIコードと10Hずれている。) 412B:51 62 55 51 54 DC 51 0C A3 51 5E 54 81 13 12 A R E A D A N D  AREADから始まっています。次に命令の処理アドレスを調べるのですが、 ROMのアドレスは4000Hから7FFFHとわかっていますので、そのあ いだに入る数値を探せば良いわけです。ここでは命令の直後の2バイトが処理 アドレスになっています。  次はPC−1600Kの場合です。これも同じですがバンク切り替えがある ために少し厄介です。それでもROMの中をみていきますとバンク6の&B7 1Bから文字列が現れてきます。 +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A B714:00 F6 59 9A F1 28 04 4E 45 58 54 N E X T B71F:00 02 02 6D F1 21 03 4E 4F 54 N O T どうやらNEXT命令から始まっているようです。ここで本来はどの部分が 中間コードなのかを調べるわけですが、この場合は参考書類としてPC−15 00機械語の手引というのを使いました。これによるとPC−1500でNE XT命令の中間コードはF1H 9AHとなっています。PC−1500コン パチのPC−1600KでもNEXT命令の中間コードは同じになっているは ずです。従って3バイト目と4バイト目は中間コードであると類推できます。 また6バイト目は命令の長さであろうと判断できます。次に先頭の3バイトで すが調べていくと次のようなことがわかりました。 1:1バイト目は00H、06H、80Hのどれかである。 2:1バイト目が06Hの場合、2−3バイト目は4000H以上である。 3:1バイト目が80Hの場合、大部分は2−3バイト目が00になっている。 4:関数はすべて00H 02H 02Hである。  これらのことから1バイト目はバンク切り替えに関するもので、2−3バイ ト目が処理アドレスになっているものと判断しました。すると最後は5バイト 目ですがこれは命令の性質(文字令命令であるとか、コマンドであるとか)を 表すものであるらしいとはわかりましたが具体的にどうなっているのかは発見 できませんでした。  最後にPC−E500の場合です。これもROMをみていきますと&HF5 ADAから中間コード表がありました。 F5ADA:03 41 53 43 D0 03 41 4E 44 A1 A S C A N D  これでASC命令の内部コードがD0H(実際にはFEHがつくので2バイ トになる)であることはわかりました。しかし今回は処理アドレスなどか書き 込まれていません。そこでもう一度ダンプして見ると、この直前にアドレスら しき物がたくさん書いてあります。 F57CF:F4 DC 4F D2 F5 4E  ここが命令の処理アドレスになっています。つまりASC命令の処理アドレ スはFDCF4Hであるということがわかります。(実際は関数の場合はここ のアドレス+3にジャンプします。) 2.2 PC−1470Uのパスワード  ポケコンうらわざ大事典partIの目玉であった、PC−1470Uのパ スワードの部分です。そもそもの発端は、大型計算機のシステム破りをする人 もいるのだから、どーせポケコンのパスワードなんて大したものではないだろ う。というとっても不純な動機から始まったものでした。したがって最初っか ら、大した成果は得られないだろうと思っていましたが、ふとしたことからと んでもないことがわかってしまったという例です。  解析は、まずパスワードの入っている番地を探すことから始めました。パス ワードといえども必ずメモリーの中に入っているわけですから、パスワードを 設定してからメモリー・ダンプ・プログラムで、メモリーの中にパスワードと 同じ文字があるかどうかを見ればいいのです。実際に実行させると簡単に&F FE0にパスワードがあることがわかることでしょう。  次に考えたのは、POKE文一つでパスワードがはずせないかということで す。すでに調べたパスワードの記録場所にはパスワードがかかっていないとき にも、その前に指定していたパスワードが入っていました。ということはパス ワードが掛かっているかどうかは、もっと別のところに記憶しているに違いな いと考えました。そこで、ポケコンのワークエリアをすべてメインメモリーに 記憶させ、パスワードが掛かっているときといないときの違いを調べてみまし た。次に実際にその違っている場所をPOKEで操作してみてパスワードが掛 かるかどうかをやっていけば良いのです。このようにして調べていくと、&F FEAがパスワードが掛かっているかを示している場所であるということがわ かりました。  しかし、ここで大きな問題があることがわかりました。実はPC−1470 Uではパスワードが設定されるとPOKEやPEEKが使えないのです。とい うことはせっかくパスワードの場所や、パスワードが掛かっているかどうかを 示す場所が判っても実際には使うことが出来ないということになります。  これはふとしたことから解決してしまいました。実はパスワードフラグを探 すときに、AER(数式記憶機能)にPEEK文を入れておいたのですが、あ る時パスワードが掛かっているのを忘れて、ちょいと実行させてみたらなんと PEEK文が使えてしまったのです。よく調べてみると電源を入れてからエラー が発生するまでは使用可能なことが判ったのです。これらを基にしてポケコン うらわざ大事典partIが作られたのです。 2.3 PC−E500のブザー  これはPC−E500でミニオルガンを作ろうと思った際に実施したもので す。オルガンですから当然音を出さなければなりません、したがって音を出す にはどうしたら良いのかを調べる必要があります。  この場合、BASICで音を出す命令にBEEPがあるので、BEEP命令 を逆アセンブラで調べることにしました。BEEP命令の場所はすでにわかっ ているので、そこからみていくと次のような命令に出会いました。 F8123: OR (0FDH),010H  FDHはシステムコントロールレジスタ(SCR)です、どうやらここが怪 しそうです。というので実際にプログラムを作ってみたらどうなるかは、すで にマシン語の解説のところでやった通りです。 EX版あとがき これを書いた1990ごろからポケコンがあまり発売されなくなりました。ま あ、いまどきプログラム学習用にポケコンを買う人もいないですし、普通の用 途なら関数電卓でも充分なのでしょう。まあ、この文章もほとんど過去の遺物 となってしまったわけですがこのまま腐らせておくのももったいないので、公 開しておきます。 ポケコンうらわざ大事典 Part I あとがき(1988年) とにかく時間がなかったので、自分で解析したのは、パスワード、同時キー 入力、バンク切り替えの部分だけでした。ポケコンの解析をするのはおもしろ いですよ。昔、PC−1251が発表された頃、かくし命令をすべて解析し、 SC61860のマシン語の命令も解析をやりました。ただ4つの命令(今で 言うLIA,RTN,CALL,JP)しか分かりませんでしたが...。と いうわけで皆さんもどんどん解析をして発表して下さい。しかし、マシン語の プログラム開発にはアセンブラとディスアセンブラは必須ですね。手でやって いると、マシーンコードを覚えてしまいます。私の場合、SC61860を始 めLH5801、Z80、i8086などをやっているので頭が混乱しそうで す。ところで、PC−1470Uを含めて最近のシャープのPC−12系(C PUにSC61860を使ったもの)のポケコンの構造がきたなくなっている と思いませんか。特にPC−1360Kなどははっきりいって無謀だとおもい ます。ただでさえ遅いCPUを使っているのにバンク切り替えをしてさらに遅 くなっていて、文節変換機能など使い物になりません。私は、PC−12系よ りも、LH5801を使ったPC−15系の方がすっきりしてて好きです。Z 80登載のPC−1600Kになるとバンク切り替えの塊にも関わらず速いの 一言です。と言うわけで、PC−1470Uの後継機は、PC−1470U+ 4段液晶+漢字表示という方向ではなく、PC−1600K+関数電卓の方向 に進んでほしいと思います。 参考文献  皆さんがポケコンのことを知るときに役に立つであろうと思われる資料です。 PC−1500 機械語の手引き シャープ  PC−1500のCPUの解説から始まって、BASICの内部構造などが 詳しく書いてある資料です。シャープ唯一の市販された資料でもあります。 PC−1600K データブック 工学社  PC−1600Kのことならこの本が一冊あれば十分というぐらい内容が豊富な本。 ポケコン・マシン語入門 工学社  PC−1250シリーズなどの機械語の解説が書いてあります。PC−12 50のユーザーならぜひもって置きたいところです。また、PC−1500に ついても「機械語の手引き」にない情報なども掲載されています。 ポケコン・マシン語ブック 工学社  PC−1350/1400シリーズの内部資料が掲載されています。たくさ んの機種のプログラムやハード制作記事が載っています。 ポケコン・ジャーナル 工学社  最新のポケコンの情報などが載ります。  今回の原稿を作成するにあたり、上記の本と各ポケコンの取扱い説明書を使 用しました。