FX-870P/VX-4 マニュアルに戻る

FX-870P/VX-4 内部情報


本情報は,PJ 1991年7月号掲載の「FX-870P解析詳細」(こたちゃん)を中心にまとめて,足りない情報の追加や修正を施したものである。
「FX-870P解析詳細」の機械語関連の情報については,現在,http://pb-prog.sakura.ne.jp/fx-870p.htmlでも閲覧できる。




1. 機械語関連

1-1. メモリ・マップ
FX-870P,VX-4は4つのメモリ・バンク(64KB×4)を持っている。 全体のメモリ・マップは図1に示す。特徴は,以下の通り。

  1. BANK0~3に,それぞれROM, RAM, ROM, I/Oが割り当てられた整然とした配置であり,FX-870Pと同じCPUを持つPB-1000(A-1.参照)と比較して, メモリアクセスに関してプログラムしやすいなどの利点がある。
  2. BANK0のROMに,全てのシステム・プログラム(BASIC, C, CASL)がある。
  3. BANK1のRAMにおいて,0000H~0FFFHの4KBはシステム側は全く使っておらず,VX-4ではメモリが存在しない。
  4. BANK2のROMに,海外向けキャラクタ・フォント,各種メッセージ,トレーニング・ボード用のプログラムなどが格納されている。
  5. BANK3は,I/Oに利用されている。8000H~8007Hには30-pin コネクタのアドレス0~7が割り当てられており, DEFSEG=&H1000とすることで, PEEK,POKEの引数のアドレスが0~7によって入出力できるようになっている。
このうち,BANK1の未使用の最初の4KBは,機械語プログラムの格納に適している。

図1.FX-870P メモリ・マップ

表1.BANK 3 ROM詳細
開始アドレス
(16進)
ROM 内容
0000H標準キャラクタ・フォント
0540H海外向けキャラクタ・フォント
0A80HBASIC エラーメッセージテーブル
0EA8H未使用
13F7HF.COM, CASL, FX, システムメッセージ用データエリア
2739H未使用
27D4HROM チェックプログラム用データエリア
2AD9H未使用
2E1EH3 pinでの通信用BASICプログラム等
38C4HC言語コマンドテーブル
3BCBH未使用
4248HC言語エラーメッセージテーブル
47CFH不明
4C9CH未使用



1-2. システム・エリア(BASIC時)
 BANK1の0000H~0FFFHは未使用。1000H~1CD0Hは、システムエリアとして、表2 のように使用されている。


表2.システム・ワークエリア一覧
データ分類LABELADDRESS
(16進)
BYTE数説明
 データ  INTOP 1000 256 中間コード・バッファ
 LCDST 1100 1 7bit:NONE
 6bit:NONE
 5bit:反転表示(ON/OFF)
 4bit:カーソルバー ON/OFF
 3bit:カーソル移動範囲指定
 2bit:仮想スクリーン/実スクリーン
 1bit:仮想表示イネーブル
 0bit:KEY 入力時/PRINT
 EDCSR
 SCTOP
 TOEDB
 BOEDB
 MOEDB
 1101
 1102
 1103
 1104
 1105
 1
 1
 1
 1
 1
 カーソル位置
 実スクリーン・トップ(上位3ビット・下位5ビット0)
 論理行トップ(上位3ビット・下位5ビット0)
 論理行ボトム(上位3ビット・下位5ビット1)
 論理行トップ(INPUT時)
 TOARE
 BOARE
 1106
 1107
 1
 1
 カーソル移動範囲トップ
 カーソル移動範囲ボトム
 EDCNT
 DSPMD
 SCROL
 1108
 1109
 110A
 1
 1
 1
 入力した最後の文字の位置+1
 00H=ノーマル表示/01H=PF表示
 80H=4行スクロール/60H=3行スクロール/40H=2行スクロール/20H=1行スクロール
 ELVAD

 110B
 110D
 2
 6
 コントラスト・データ(ROMのアドレス)
 不明
 キー・データ  KEYMD 1113 1 6bit:カナ
 5bit:NONCAPS
 KYSTA 1114 1 7bit:AC
 6bit:OFF
 5bit:APO禁止
 4bit:コントラスト
 3bit:REPEAT イネーブル
 2bit:REPEAT ON/OFF
 1bit:0
 0bit:0
 CHATA 1115 1 チャタリングの時間カウント用
 KEYCM
 KEYIN
 1116
 1117
 1
 2
 KO
 KI
 KYREP
 
 1119
 111A
 1
 1
 キーリピート・カウント時間
 不明
 KECNT 111B 22 キー・バッファ
   1バイト: 00Hポインタ基準
   2バイト: バッファ中ポインタ
   1バイト: 10Hバッファ長
   2バイト: バッファ開始アドレス
   16バイト: バッファ
  1131 1 不明
 BASIC データ1  ANGFL
 RNDFL
 
 1132
 1133
 1134
 1
 1
 1
 角度モード(0:DEG, 1:RAD, 2:GRA)
 0:演算後丸めをする(MODE10), 1:演算後丸めをしない(MODE11)・・・(注1)
 不明
 スクリーン・データ  CSRDT
 EDTOP
 LEDTP
 1135
 113B
 123C
 6
 257
 768
 カーソル点滅用データ・バッファ
 入力バッファ
 表示ドット・バッファ
 CGRAM 153C 24 キャラクタ・コード FCH~FFH用表示ドット・パターン
 I/O データ  RS1 1554 1  7,6,5bit:
     (1 1 1)・・・ 75 baud(未確認)
     (1 1 0)・・・ 150 baud
     (1 0 1)・・・ 300 baud
     (1 0 0)・・・ 600 baud
     (0 1 1)・・・ 1,200 baud
     (0 1 0)・・・ 2,400 baud
     (0 0 1)・・・ 4,800 baud
     (0 0 0)・・・ 9,600 baud(使用確認)
 4bit: ストップ・ビット 1/2
 3bit: データ長(bit) 7/8
 2bit: パリティ ON/OFF
 1bit: パリティ Odd/Even
 0bit: MT/RS-232C
 RS2 1555 1 1bit: 入力用 SO中
 0bit: 出力用 XOFF中
 RS3 1556 1 7bit: NONE
 6bit: 入力用 XOFF中
 5bit: 出力用 SO中
 4bit: CD 制御指定
 3bit: DSR 制御指定
 2bit: CTS 制御指定
 1bit: XON/XOFF 指定
 0bit: SI/SO 制御指定
 RS4 1557 1 4bit: フレーミング
 3bit: パリティ
 2bit: オーバーラン
 1bit: not Ready
 0bit: バッファ
 INTCK 1558 1 01H・・・データ受信
 RXCNT 1559 258 RS-232C, MT用受信バッファ
    1byte: 受信バッファ数
    1byte: 入力用ポインタ
    256byte: 受信バッファ
  165B 1 不明
 ACJMP 165C 2 BREAK時のジャンプ先アドレス
 BASIC データ2  WORK1 165E 28 WORK バッファ
  167A 4 未使用(?)
 VAR1
 VAR2
 VAR3
 VAR4
 167E
 167F
 1680
 1681
 1
 1
 1
 2
 変数用ワーク
 変数用ワーク
 変数用ワーク
 変数用ワーク
 PASS 1683 8 パスワード格納エリア(XOR255 で入っている)
 CASPN
 CPN
 168B
 168C
 1
 1
 CASL プログラム・ナンバー
 C言語 プログラム・ナンバー
 
 
 168D
 168E
 1
 41
 不明
 不明
 FCOMD



 FCOM1
 FCOM2
 1687



 1688
 1689
 1



 1
 1
 F.COMのデバイスで,(000000AB)B.
    AB=00・・・RS-232C
    AB=01・・・DISK
    AB=10・・・MT
 F.COM P/F
 F.COM 番号
  16BA 5 不明
 OPTCD
 SEGAD
 16BF
 16C0
 1
 2
 オプション・コード
 セグメントの値
  16C2 1 不明
 SETDA 16C3 1  SET命令のデータ (00AB####)Bで,
   E…A=1/F…B=1/####=BCD桁数
 MODE1 16C4 1 確認不可能
 MODE2 16C5 1 FX-870P/VX-4では常に0と思われる。
 MODE3 16C6 1 01H: BASIC実行中(RUN)
 02H: BASIC停止中(STOP)
 00H: その他
 
 NOWFL
 NOWLN
 EXEDE
 16C7
 16C9
 16CB
 16CD
 2
 2
 2
 2
 下と同じ
 現在使用しているファイルの番地
 現在実行している行番号
 現在実行している命令の番地
  16CF 12 不明
 DATPA
 CONTA
 ERRFL
 EJPDE
 ERRLN
 ERRDE
 ERRN
 EJPFG
 TRAFG
 INPER
 STAT
 OUTDV
 IOSTS
 PRSW
 PTABC
 
 RSFG
 RND
 
 ANSAD
 
 
 
 FDDBF
 16DB
 16DD
 16DF
 16E1
 16E3
 16E5
 16E7
 16E8
 16E9
 16EA
 16F1
 1739
 173A
 173B
 173C
 173D
 173E
 1740
 1749
 174A
 1753
 1770
 1790
 1793
 2
 2
 2
 2
 2
 2
 1
 1
 1
 2
 72
 1
 1
 1
 1
 1
 2
 9
 1
 9
 29
 35
 3
 258
 DATA文ポインタ
 CONT時に実行を再開するポインタ
 ON ERROR 有効ファイル DIR アドレス
 ON ERROR 飛び先ポインタ
 エラー発生行番号
 エラー発生文ノアドレス
 エラー番号
 00H:通常処理中/01H:ON ERROR処理中
 00H:TROFF/01H:TRON
 INPUT エラー時の戻りアドレス
 STAT 用データ
 出力デバイス(00:表示, 02:プリンタ, 04:FCB)
 IBIT ON 受信オープン/OBIT ON 送信オープン
 PRT ON/OFF (1/0)
 プリンタ出力文字数
 不明
 RS-232Cデフォルト値(RS1,RS3のDATA)
 乱数データ
 不明
 ANS用データ
 不明
 FILE ワーク(?)
 不明
 FDD バッファ
メイン・データ  IOBF
 SSTOP
 SBOT
 FORSK
 GOSSK
 TONDT
 DTTB
 TOSDT
 PTSDT
 P0STT
 P1STT
 P2STT
 P3STT
 P4STT
 P5STT
 P6STT
 P7STT
 P8STT
 P9STT
 F0STT
 F1STT
 F2STT
 F3STT
 F4STT
 F5STT
 F6STT
 F7STT
 F8STT
 F9STT
 MEMEN
 DIREN
 CALC
 IOBUF
 1895
 1897
 1899
 189B
 189D
 189F
 18A1
 18A3
 18A5
 18A7
 18A9
 18AB
 18AD
 18AF
 18B1
 18B3
 18B5
 18B7
 18B9
 18BB
 18BD
 18BF
 18C1
 18C3
 18C5
 18C7
 18C9
 18CB
 18CD
 18CF
 18D1
 18D3
 19D5
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 2
 258
 258
 I/O バッファの先頭番地
 文字演算ワーク先頭番地
 スタック・フリーエリア先頭番地
 FOR スタック・ポインタ
 GOSUB スタック・ポインタ
 数値変換データ
 変数テーブル
 文字変数データ
 文字データ・フリーエリア
 P0先頭番地
 P1先頭番地
 P2先頭番地
 P3先頭番地
 P4先頭番地
 P5先頭番地
 P6先頭番地
 P7先頭番地
 P8先頭番地
 P9先頭番地
 F0先頭番地
 F1先頭番地
 F2先頭番地
 F3先頭番地
 F4先頭番地
 F5先頭番地
 F6先頭番地
 F7先頭番地
 F8先頭番地
 F9先頭番地
 ファイル・フリーエリア先頭番地
 RAMエンド・アドレス
 カルク用バッファ
 SAVE/LOAD用I/Oバッファ
スタック  SSPBT
 SSPTP
 USPBT
 USPTP
 1AD7
 1BD7
 1BD7
 1CD0
 256
 0
 249
 0
 
 システムスタック・エリア
 
 ユーザースッタク・エリア

(注1) 『FX-870P解析詳細』では,MODEDと表記されていたが,四則演算後の丸めの有効・無効を決定するデータと判明したので, 『Z-1/FX-890P活用研究』記載のFX-890P/Z-1の同等のシステムエリアデータの名前 ROUNDFLGをFX-870P(PB-1000)の命名法に従って,今回,RNDFLと表記することにした。




1-3. ROM ルーチン
現在までに確認されている使用可能なBANK1のROM ルーチンを表3に示す。『PB-1000テクニカル・ハンドブック』と同じルーチンについては名前はそのままで,それ以外はこたちゃんが命名。 なお,ROM ルーチンの機械語プログラムからの呼び出し方は,1-5.で説明する。
表3. FX-870P ROM ルーチン一覧表
ラベル名アドレス機能
 NEXTC 0049H (73)  IZで指定されるアドレスからサーチを開始し,スペース(20H)以外のコードが見つかれば,そのコードを$0に入れる。
 [入力]
   IZ: サーチ開始アドレス
 [出力]
   IZ: $0にあるコードが存在するアドレス
   $0: スペースでない最初のコード
 ENDSC 003CH (60)  NEXTC を実行して,$0の値が0,1,2ならば,フラグ・レジスタのキャリーをON(1)
 [入力]
   IZ: サーチ開始アドレス
 [出力]
   IZ: $0にあるコードが存在するアドレス
   $0: スペースでない最初のコード
   FLG: キャリー・フラグ=1@$0=0,1,2
 OKNMI 002BH (43)  $0の値が数字(ASCIIコードの30H~39H)のとき,フラグ・レジスタのキャリーをON(1)にする。
 [入力]
   $0: チェックするコード
 [出力]
   $0: コード
   FLG: キャリー・フラグ=1@$0=30H~39H
 OKAMI 00ABH (171)  $0の値がアルファベト大文字(A~Z)のとき,フラグ・レジスタのキャリーをON(1)にする。
 [入力]
   $0: チェックするコード
 [出力]
   $0: コード
   FLG: キャリー・フラグ=1@$0="A"~"Z"
 FC07 00E9H (233)  IZで指定されるアドレスからサーチを開始し,スペース(20H)以外のコードが見つかれば,そのコードと次のアドレスのコードの2バイトに対して$1(7が格納される), $2を比較する。その結果,一致したらゼロ・フラグをON(1)にする。
 [入力]
   IZ: サーチ開始アドレス
   $2: セカンド・コード
 [出力]
   $1: 07H
   $2: セカンド・コード
   FLG: ゼロ・フラッグ 1@一致/0@不一致
   IZ: 最初に見つけたコードのアドレス+2@Z=1/不変@Z=0
   内容が破壊されるレジスタ $0

  ☆同一系列のルーチン
   FC06 00EBH(235)  $1=06H
   FC05 00EDH(237)  $1=05H
   FC04 00EFH(239)  $1=04H
  で,他はFC07と全く同じ。このルーチンはBASIC命令の判定に用いられる。
 SCF2F 00BBH (187)  NEXTCを実行後,$0の値と$1(=2FH)が一致したら,ゼロ・フラグをON(1)にする。
 [入力]
   IZ: サーチ開始アドレス
 [出力]
   $0: スペースでない最初のコード
   $1: 2FH
   FLG: ゼロ・フラッグ 1@($0)=($1)/0@($0)<>($1)
   IZ: 最初に見つけたコードのアドレス+1@Z=1/不変@Z=0

  ☆同一系列のルーチン
   SCF3A 00BDH(189)  $1=3AH
   SCF22 00BFH(191)  $1=22H
   SCF40 00C1H(193)  $1=40H
   SCF2C 00C3H(195)  $1=2CH
   SCF28 00C5H(197)  $1=28H
   SCF29 00C7H(199)  $1=29H
   SCF2D 00C9H(201)  $1=2DH
   SCF3B 00CBH(203)  $1=3BH
   SCF23 00CDH(205)  $1=23H
   SCF2E 00CFH(207)  $1=2EH
   SCFXX 00D1H(209)  $1=直前自分で入力した値
  で,他はSCF27と全く同じ。
 SCE3B 00D7H (215)  NEXTCを実行後,$0の値と$1(=3BH)が一致したら,ゼロ・フラグをON(1)にする。一致しなかったら,SNerrとなる。
 [入力]
   IZ: サーチ開始アドレス
 [出力]
  FLG: ゼロ・フラッグ 1@($0)=($1)/0@($0)<>($1)
   Z=1のとき
     $0: スペースでない最初のコード
     $1: 3BH(";")
     IZ: 最初に見つけたコードのアドレス+1
   Z=0のとき
     SNerr

  ☆同一系列のルーチン
   SCE24 00D9H(217)  $1=24H
   SCE2C 00DBH(219)  $1=2CH
   SCE2D 00DDH(221)  $1=2DH
   SCE29 00DFH(223)  $1=29H
   SCE28 00E1H(225)  $1=28H
   SCF3D 00E3H(227)  $1=3DH
   SCEXX 00E5H(229)  $1=直前自分で入力した値
  で,他はSCE3Bと全く同じ。
 TCAPS 00B6H (182)  $0にあるアルファベット小文字コードをアルファベット大文字コードへ変換する。アルファベット小文字コード以外の場合,変換しない。
 [入力]
   $0: アルファベット小文字コード
 [出力]
   $0: アルファベット大文字コード
 CHEXI 009DH (157)  $0にあるコードが文字の0から9,A~F,a~f(30H-3H, 41H-46H, 61H-66H)である場合,$0が16進数文字として数値(00H-0FH)に変換する。
 [入力]
   $0: 16進数の文字コード
 [出力]
   $0: 16進数変換値(00H-0FH)
 CLEME 014CH (332)  $0, $1で指定サレタアドレスから,$2, $3で指定されたバイト数分を0クリアする。$2, $3が0の場合,実行しない。
 [入力]
   $0, $1: クリアするスタート・アドレス
   $2, $3: クリアするバイト数
 [出力]
   IZ: クリアが終了したアドレス+1
   $5~$13: 全て0
   内容が破壊されるレジスタ $0~$2, $14
 CLEDB 9338H (37688)  BANK1のEDTOP(113BH-123BH), LEDTP(123CH-153BH)の内容を0クリアし,各ポインタをCLSにセットする。
 [出力]
   IX: EDCSR(1101H)の内容
   IZ: MOEDB(1105H)の内容
   内容が破壊されるレジスタ $0~$14
 DOTDS 930FH (37647)  DSPMD(1109H)の内容にしたがって,全画面表示を行う。LEDTP(123CH-153BH)+SCTOP(1102H)×6から,3行または4行の内容をLCDに転送する。
 [入力]
   DSPMD(1109H)の内容によって,3行か4行かを決定する。
 [出力]
   なし
   内容が破壊されるレジスタ $0~$15, IX
 BRSTR 297AH (10618)  $2, $3の内容をACJMP(165CH, 165DH)に入れる。
 [入力]
   $2, $3: データ
 [出力]
   なし
   内容が破壊されるレジスタ IX
 CRTKY 23C8H (9160)  コントラスト・キー実行のKEYサンプル・フロー。BREAKキーはACJMP(165CH, 165DH)で指定されたアドレスへジャンプする。
 [入力]
   なし
 [出力]
   $0: キーコード(表4 参照)が入る。
   内容が破壊されるレジスタ $1~$11, IX, IZ
 KYCHK 506EH (20590)  OFF, BREAK, STOPの各キーをチェックする。
 [入力]
   なし
 [出力]
   FLG:ゼロ・フラグ=1@STOPキー
   内容が破壊されるレジスタ $0~$4
 BKCK 29C5H (10693)  OFFキーのチェックおよびBREAKキーのサンプリングを行う。
 [入力]
   なし
 [出力]
   なし
   内容が破壊されるレジスタ $0~$4
 OUTCR 2AE8H (10984)  デバイスに対して,0DH,0AH(CR, LF)を出力する。
 [入力]
   デバイスはOUTDV(1739H)の内容によって決まる。
 [出力]
   なし
   内容が破壊されるレジスタ $0~$13, $16, IX
 PROUT 89A9H (35241)  $16の内容をプリンタに出力する。プリンタに繋がっていない場合,NRerrorとなる。
 [入力]
   $16: プリンタに出力するデータ
 [出力]
   なし
   内容が破壊されるレジスタ $0~$6, IX
 DTBIN 1EE6H (7910)  IZで指定されるアドレスに存在するASCIIコードを10進数として数値に変換する。
   ・変換結果が65536以上になる場合,OVエラーとなる。
   ・数字文字(30H-39H)が存在しない場合,0を返す。
   ・数字文字(30H-39H)以外のコードが存在すれば,直ちに終了。このとき,スペースは読み飛ばす。
 [入力]
   IZ: 数値に変換しようとする文字列の先頭のアドレス
 [出力]
   IZ: "0"-"9"(30H-39H)以外のデータが存在するアドレス
   $17, $18: 変換結果の値
   内容が破壊されるレジスタ $0~$3, $16
 BINMZ 0EFDH (3837)  $10~$18に入っている実数型数値x が-32769  [入力]
   $10~$18: 実数型数値
 [出力]
   $15, $16: 整数型数値
   内容が破壊されるレジスタ $10~$14, $17~$18, IX
 BIN01 0EC6H (3782)  $10~$18に入っている実数型数値x が 0<=x<256であれば,整数型数値に変換する。範囲外であれば,BSエラーとなる。
 [入力]
   $10~$18: 実数型数値
 [出力]
   $15, $16: 整数型数値
   内容が破壊されるレジスタ $10~$14, $17~$18, IX
 BIN11 0ECEH (3790)  $10~$18に入っている実数型数値x が 1<=x<256であれば,整数型数値に変換する。範囲外であれば,BSエラーとなる。
 [入力]
   $10~$18: 実数型数値
 [出力]
   $15, $16: 整数型数値
   内容が破壊されるレジスタ $10~$14, $17~$18, IX
 BIN02 0EE2H (3810)  $10~$18に入っている実数型数値x が 0<=x<65536であれば,整数型数値に変換する。範囲外であれば,BSエラーとなる。
 [入力]
   $10~$18: 実数型数値
 [出力]
   $15, $16: 整数型数値
   内容が破壊されるレジスタ $10~$14, $17~$18, IX
 BIN12 0EE8H (3816)  $10~$18に入っている実数型数値x が 1<=x<65536であれば,整数型数値に変換する。範囲外であれば,BSエラーとなる。
 [入力]
   $10~$18: 実数型数値
 [出力]
   $15, $16: 整数型数値
   内容が破壊されるレジスタ $10~$14, $17~$18, IX
 SIKI 1088H (4232)  式(文字式でもよい)を実行し,結果を求める。
   ・結果が数値のとき,$10~$18に実数型数値として格納される。
   ・結果が文字列のとき,RAMのフリー・エリアに格納され,$15, $16に文字列のスタート・アドレス,$17に文字長が入る。
 [入力]
   IZ: 式が格納されているRAMのスタート・アドレス。式中の予約語(関数など)は内部コードに変換されてなければならない。
 [出力]
   IZ: 式の終わり+1のアドレス
   ・結果が数値のとき
     $10~$18: 実数型数値
     FLG: キャリーをOFF(0)にする。
   ・結果が文字列のとき
     $15, $16: 文字列のスタート・アドレス
     $17: 文字列の長さ
     FLG: キャリーをON(1)にする。
 EXPRW 112FH (4399)  数式を実行し,結果を求める。
 [入力]
   IZ: 式が格納されているRAMのスタート・アドレス。式中の予約語(関数など)は内部コードに変換されてなければならない。
 [出力]
   IZ: 式の終わり+1のアドレス
   $10~$18: 実数型数値
 NISIN 0AFAH (2810)  $17の値がBCD数値として.バイナリ変換する。
 [入力]
   $17: BCD数値
 [出力]
   $17: バイナリ変換値
   内容が破壊されるレジスタ $19
 SIKI2 11D2H (4562)  文字式を実行し,結果を求める。
 [入力]
   IZ: 式が格納されているRAMのスタート・アドレス。式中の予約語(関数など)は内部コードに変換されてなければならない。
 [出力]
   IZ: 式の終わり+1のアドレス
   $15, $16: 文字列のスタート・アドレス
   $17: 文字列の長さ
 INKEY 191DH (6429)  INKEY$のサブルーチン。
 [入力]
   なし
 [出力]
   $15, $16: キー入力されたデータ(表5参照)が格納されたアドレス
   $17: 0@キー入力なし/1@キー入力あり
   内容が破壊されるレジスタ $0~$5, $18, IX
 ??err 下記  BASICのエラー発生。実行後,BASICまたはCALモードの入力待ちになる。
 [入力]
   なし
 [出力]
   なし
   エラー名とそのアドレスは,以下の通り。
     LBERR ・・・ 2B5EH (11102)(注1,2)
     OMERR ・・・ 2B6DH (11117)
     SNERR ・・・ 2B70H (11120)
     STERR ・・・ 2B74H (11124)
     TCERR ・・・ 2B78H (11128)
     BVERR ・・・ 2B7CH (11132)
     NRERR ・・・ 2B80H (11136)
     RWERR ・・・ 2B84H (11140)
     BFERR ・・・ 2B88H (11144)
     BNERR ・・・ 2B8CH (11148)
     NFERR ・・・ 2B90H (11152)
     FLERR ・・・ 2B94H (11156)
     OVERR ・・・ 2B98H (11160)
     MAERR ・・・ 2B9CH (11164)
     DDERR ・・・ 2BA0H (11168)
     BSERR ・・・ 2BA4H (11172)
     FCERR ・・・ 2BA8H (11176)
     ULERR ・・・ 2BACH (11180)
     TMERR ・・・ 2BB0H (11184)
     REERR ・・・ 2BB4H (11188)
     PRERR ・・・ 2BB8H (11192)
     DAERR ・・・ 2BBCH (11196)
     FOERR ・・・ 2BC0H (11200)
     NXERR ・・・ 2BC4H (11204)
     GSERR ・・・ 2BC8H (11208)
     FMERR ・・・ 2BCFH (11215)
     FDERR ・・・ 2BD3H (11219)
     OPERR ・・・ 2BD7H (11223)
     AMERR ・・・ 2BDBH (11227)
     FRERR ・・・ 2BDFH (11231)
     POERR ・・・ 2BE3H (11235)
     DFERR ・・・ 2BE7H (11235)
 BEEP 33B3H (13235)  BASICのBEEP音を発生。
 [入力]
   なし
 [出力]
   なし
   内容が破壊されるレジスタ $0~$3
 ENLST 508BH (20619)  内部コードで格納されているBASICプログラムを,IZが指定するアドレスから1行分をASCIIコードに変換し,INTOP(1000H-10FFH)に格納する。
 [入力]
   IZ: 変換するBASICプログラムの行が開始するアドレス
 [出力]
   IZ: 次の行の先頭アドレスまたはプログラム・エンド(0)
   内容が破壊されるレジスタ $0~$16, IX
 RSOPN 84ECH (34028)  RS-232Cのハード的なオープンを行う。
   ・ボーレートの設定
   ・DTR, RTSをONにする。
 [入力]
   $00: オープンのモード=01H@送信/02H@受信/03H@送受信
   $11: RS1(1554H)に入れた値
   $13: RS3(1556H)に入れた値
  このルーチンを呼ぶ前に,ワークエリアのRS1RS4を設定しておかなければ,正常に動作しない。
 [出力]
   なし
   内容が破壊されるレジスタ $0~$6, IX
 RSCLO 8563H (34147)  RS-232Cのハード的なクローズを行う。
 [入力]
   なし
 [出力]
   なし
   内容が破壊されるレジスタ $0~$3, IX
 RSGET 8590H (34192)  RS-232Cの受信バッファから1文字取り出す。バッファが空の時は,データを受信するまで待つ。
   ・XON/XOFFを指定していて,XOFFの状態の場合,まずバッファから1文字取り出す。そして残りの文字が32文字以下になれば,XONを送信する。
   ・エラーを検出した場合,各エラーにジャンプする。
 [入力]
   なし
 [出力]
   $0: 受信データ
   内容が破壊されるレジスタ $1~$4, IX
 PRTRS 85FBH (34299)  $16のデータをRS-232Cで送信する。
   ・XON/XOFFを指定していて,XOFFの状態の場合,XONになるまで待つ。
   ・SI/SOを指定している場合は,その制御を行う。
 [入力]
   $16: 送信データ
 [出力]
   なし
   内容が破壊されるレジスタ $0~$4, IX
 NTX 865CH (34396)  $0の内容をRS-232Cで送信する。
   ・XON/XOFF,SI/SOの指定に関係なく,$0の内容を送信する。
 [入力]
   $0: 送信データ UAレジスタの上位2bit=11
 [出力]
   なし
 DOTMK 977FH (38783)  $10, $11で指定されるEDTOP(113BH-123BH)中のキャラクタが持つドット・パターンを,LEDTP(123CH-153BH)へ作成する。
 [入力]
   $10: スタート・カーソル・アドレス
   $11: エンド・カーソル・アドレス
 [出力]
   なし
   内容が破壊されるレジスタ $0~$11, IX, IZ

(注1)陶治彩絵, PJ 1991年2月号, p.106,『FX-870PのROM解析』.
(注2)CASIOの『VX-4 操作テキスト』,p.93のエラーメッセージ一覧表には記載されていないエラー。"Low Battery"の略?


表4. CRTKY(23C8H) によるキーコード表
 上位 4ビット
    0        1        2        3         4        5        6        7         8        9        A        B         C        D        E        F    
 下 
 位 
 4 
 ビ 
 ッ 
 ト 
  0    F.TOPSPC0 @Pp PRINT3Ε  ENGP0
  1   F.ENDDEL!1 AQaq SYSTEMX2 TABP1
  2   L.TOPINS"2 BRbr CLEARhypX3 MRP2
  3     #3 CScs CONTSET  MinP3
  4     $4 DTdt RENUMFACT  M+P4
  5   L.CAN %5 EUeu RUNRAN#  M-P5
  6   L.END &6 FVfv EDITπ INP6
  7     '7 GWgw lognPr OUTP7
  8   BS (8 HXhx lnnCr CALCP8
  9     )9 IYiy exHEX$ ANSP9
  A     *: JZjz sinDEGR   
  B   HOME +; K[k{ cosDMS   
  C   CLS,< L¥l| tanPOL(   
  D   EXE-= M]m} sin-1REC(   
  E    .> N^n~ cos-1&H MEMO 
  F    /? O_o  tan-110xソ LINE 
* A0HのEは,テンキーのπのボタン
  BRK, STOP, OFF, ALL RESET, CASL, FX, C, MODE, CONTRAST ↑↓の各キーは実行。
  CAPS, カナは状態変化。


表5. INKEY(191DH) によるキーコード表
 上位 4ビット
    0        1        2        3         4        5        6        7         8        9        A        B         C        D        E        F    
 下 
 位 
 4 
 ビ 
 ッ 
 ト 
  0     SPC0  Pp        ENG 
  1      1 AQaq          
  2    INS 2 BRbr        MR 
  3    OFF 3 CScs          
  4      4 DTdt        M+ 
  5      5 EUeu          
  6      6 FVfv        IN 
  7      7 GWgw        OUT 
  8   BS (8 HXhx        CALC 
  9     )9 IYiy        ANS 
  A     *  JZjz         ALL RESET
  B     +  K k          MODE
  C   CLS,  L l           
  D   EXE-= M m           
  E    .  N^n         MEMO 
  F    /  O o         LINE 
* BRKは実行で,ACJMPで示されるアドレスに処理を移す。





1-4. キー・マトリックス
 表6 にFX-870Pのキー・マトリックスを示す。キーの取得には,まずIAレジスタに取り込みたいキーのある出力指定値("6"ならば7)を代入して, キーが押下されていれば,KYレジスタの対応するビットが1になる("6"ならば0ビット目が1になる。つまり,KY=0001H)。
 2,4,6,8SPCを同時入力で読み取れるサンプル・プログラムをリスト1に示す。 このプログラムをCALLすると,$0に以下のように結果が入って戻ってくる。
   7   
   6   
   5   
   4   
   3   
   2   
   1   
   0   
(bit)
0
0
0
SPC
8
2
4
6
で,キーが押された部分のビットが1になる。


表6.FX-870P キー・マトリックス表
 IAレジスタのキー出力指定値
    1        2        3         4        5        6         7        8        9    
 KY 
 レ 
 ジ 
 ス 
 タ 
 の 
 出 
 力 
 ビ 
 ッ 
 ト 
 位 
 置 
  0  
Fx
ln
hyp
(
9
6
3
E *
  1  
CASL
log
MR
M+
8
5
2
.
  2  
SHIFT
7
ENG
4
ANS
1
SPC
0(zero)
  3  
INS
O
P
K
L
,
=
  4  
U
I
H
J
N
M
  5  
CALC
T
Y
F
G
V
B
  6  
IN
OUT
E
R
S
D
X
C
  7 
BRK
OFF
MEMO
Q
W
RESET
A
CAPS
Z
 14  
X2
MODE
cos
tan
CLS
/
-
EXE
 15  
DEGR
sin
)
^
BS
*
+
* Eは,テンキーのπのボタン


リスト1. 同時キー入力サブルーチン
ADRS CODE LABEL MNEMONIC  コメント
xx00 02 60 1F KEY: LD $0,$31  ;結果入力レジスタのクリア($31=0)
xx03 57 00 08  PST IA,&H08  ;SPACEのチェック
xx06 42 01 04  LD $1,&H04  
xx09 77 2D xx  CAL SCAN  
xx0C 57 00 06  PST IA,&H06  ;8のチェック
xx0F 42 01 02  LD $1,&H02  
xx12 77 2D xx  CAL SCAN  
xx15 57 00 08  PST IA,&H08  ;2のチェック
xx18 42 01 02  LD $1,&H02  
xx1B 77 2D xx  CAL SCAN  
xx1E 57 00 05  PST IA,&H05  ;4のチェック
xx21 42 01 04  LD $1,&H04  
xx24 77 2D xx  CAL SCAN  
xx27 57 00 07  PST IA,&H07  ;6のチェック
xx2A 42 01 01  LD $1,&H01  
xx2D 18 60 SCAN: BIU $0  ;$0をビット・アップ
xx2F 9F 22  GRE KY,$2  ;マトリックス・キースキャン
xx31 0C 62 01  AN $2,$1  ;チェックするキーのビットを残してクリア
xx34 F0  RTN Z  ;チェックするキーが押されていなければ,戻る
xx35 0E 60 1E  OR $0,$30  ;最下位ビットを立てる($30=1)
xx38 F7  RTN   


注:オリジナルでは,サブルーチンSCANが以下のようになっているが,結果がおかしくなるので,NG。
ADRS CODE LABEL MNEMONIC  コメント
xx2D 18 60 SCAN: BIU $0  ;マトリックスキャン
xx2F 9F 22  GRE KY,$2  ;ダミー入力
xx31 9F 24  GRE KY,$4  ;本入力
xx33 81 62 04  SBCW $2,$4  ;キーチェック
xx36 B4 8A  JR NZ,SCAN  ;押されていなければ戻る。→戻ると,$0が余分にビット・アップするので,結果がおかしくなる!!
xx38 0C 62 01  AN $2,$1  ;チェックするキーのビットを残してクリア
xx3B F0  RTN Z  ;チェックするキーが押されていなければ,戻る
xx3C 0E 60 1E  OR $0,$30  ;最下位ビットを立てる($30=1)
xx3F F7  RTN   




1-5. 機械語プログラム作成における注意事項

 FX-870P/VX-4には,日立のHD61700という8-bit CPUが使われている。このCPUは,以下のレジスタを持つ(図2)。 なお,詳細は「HD61700クロス・アセンブラ」の「2-2.レジスタ構成」などを参照のこと。


図2. HD61700のレジスタ構成


 ここで,SX, SY, SZ, IB, TMは,『FX-870P解析詳細』では未知であった。 ユーザーが自由に使えるのは,$0~$29,インデックスレジスタIX, IY, IZとフラグレジスタFだけで,他のレジスタの使用には制約がある。 特に,Casioのポケコンでは,$30,$31がそれぞれ1,0固定,SX, SY, SZは 31, 30, 0に固定でそれぞれ$31, $30, $0が第2オペランドに指定された時に高速動作が可能となるよう,ROMがコーディングされている。 したがって,$30(=1), $31(=0), SX(=31), SY(=30), SZ(=0)は,絶対に内容を変えないよう注意すること。 (注)

 FX-870P, VX-4は,BASICの隠し命令 MODE110(アドレス)で自作の機械語プログラムをコールできるが,正式にはサポートされていない。 そのため,PB-1000やFX-890P/Z-1などとは異なり, FX-870P,VX-4のBASICでは,CLEAR命令で機械語領域を確保できないので, 以下のようにして機械語領域を確保する必要がある。
このように,FX-870,VX-4の機械語エリアの確保方法には一長一短がある。 また,拡張CLEARで1CD0 Hから機械語を確保しても,C言語モードでC のプログラムを実行すると,機械語エリアの情報は破壊されてしまう。 そのため,C言語から戻って機械語を実行する場合,再度,機械語をロードし直す必要がある。 一応,CASL では簡単なプログラムを実行させた後,機械語領域のデータが破壊されないのを確認したが,完全に破壊されないかは不明。

 ユーザー作成機械語プログラムからBASICへのリターン(終了)する際には,機械語プログラムのあるBANK1からBASICのROMのあるBANK0に 処理を移さなければならない。したがって,プログラムの最後でバンク切り替えが必要となるので,機械語プログラムの最後には,必ず以下のコードを加えること。


リスト2. 機械語プログラムの終了コード
ADRS CODE LABEL MNEMONIC  コメント
xxxx 56 60 54  PST UA,&H54  ;バンク0に切り替え
xxxx F7  RTN   ;RETURN


 同様に,自作機械語プログラムからFX-870PのROMのコールにはバンク切り替えが必要になる。リスト3,3-2にROMコールを行う機械語サンプルを示す。 このROMコールは,HD61700のROMコールとして有名な方法である。 まず$17,$18に呼び出すROMルーチンのアドレスを入れて,自作のBSCLLを呼んで,ここからBANK0に切り替えてジャンプする。 このプログラムでは$15~$18を使用しているが,BIOSコールでこれらのレジスタを使用する場合は,適宜レジスタを変更してプログラムする必要がある。


リスト3. ROMコールを行う機械語サンプル
ADRS CODE LABEL MNEMONIC  コメント
0000 D1 11 0F 93  LDW $17,&H930F  ;DOTDS(全画面表示)のアドレス
0004 77 0B 00  CAL RMCLL  ;ROMコールの実行
0007 56 60 54  PST UA,&H54  ;PCのBANKを0に切り替え指定
000A F7  RTN   ;BASICに戻る
000B D1 0F 23 53 RMCLL: LDW $15,&H5323  ;ROMコール・ルーチン
000F A6 10  PHSW $16  ;&H5323をシステムスタックにPUSH
0011 56 60 54  PST UA,&H54  ;PCのBANKを0に切り替え指定
0014 DE 11  JP $17  ;BIOSコール



リスト3-2. ROMコール・ルーチン
ADRS CODE LABEL MNEMONIC  コメント
000B D1 0F 23 53 RMCLL: LDW $15,&H5323  ;ROMコール・ルーチン
000F A6 10  PHSW $16  ;&H5323をシステムスタックにPUSH
0011 56 60 54  PST UA,&H54  ;PCのBANKを0に切り替え指定
0014 DE 11  JP $17  ;BIOSコール

※ "JP $17"(オペコードDEH)は,『FX-870P解析詳細』では"JP ($C5)"と表記されてきたが,Piotr Piatek氏がメインレジスタによるインダイレクトなメモリアドレス指定($C5)によるジャンプ命令(オペコードDFH)を見つけたことにより, 表記の不自然さが無視できなくなり,現在では"JP $C5"という表記に変更された。
あお氏のHD61クロスアセンブラでは,Ver0.34から"JP $C5"表記に対応しているため,旧表記のソースをアセンブルすると誤動作する。
したがって,"JP ($C5)"のニモニックがあった場合,ソースの修正が発生する可能性があるので,注意が必要である。


 また,文献(5)で紹介されていた,AI-1000のROM内に用意されたROMコール・ルーチンと同等のものを, あお氏が教えてくれたので,リスト4に示す(文献(16))。 この方法は,破壊されるレジスタが$28, $29と固定されているがリスト3より使用レジスタ数が少ないことと,リスト3より実行時間がかかることが特徴である。


リスト4. FX-870P/VX-4のROMに用意されたROMコール・ルーチンを使う方法
ADRS CODE LABEL MNEMONIC  コメント
0000 D1 1C 0F 93  LDW $28,&H930F  ;DOTDS(全画面表示)のアドレス
0004 77 0B 00  CAL RMCLL  ;ROMコールの実行
0007 56 60 54  PST UA,&H54  ;PCのBANKを0に切り替え指定
000A F7  RTN   ;BASICに戻る
000B  RMCLL:    ;ROMコール・ルーチン
000B 56 60 54  PST UA,&H54  ;PCのBANKを0に切り替え指定
000E 37 21 53  JP &H5321  ;


(注)
CASIOのポケコンにおける$30,$31の設定について
 PB-1000,FX-860P, FX-870P, VX-4等の HF61700をCPU を持つポケコンでは,$30=1, $31=0, SX=30, SY=31, SZ=0を固定して使用することが 前提になっているが,$30,$31の値の並びが1, 0なのは以下の通りと考えられる。
 HD61700クロスアセンブラはデフォルト設定で最適化オプションがONになっており,上述のカシオのポケコンのレジスタ設定前提で自分で特定レジスタを指定していなくても,自動的に特定レジスタ指定をしてくれるようになっているので, $30=1, $30=0と$30,$31,$0が特定インデックスレジスタ指定で高速化可能とだけ覚えていれば良いようになっている。






2. BASIC関連

 『FX-870P解析詳細』では,BASICの隠し命令とプログラムの格納形式しか説明がなかった。 その後,Jun Amano氏の『PB-1000/CのBASIC変数の格納形式について』において,PB-1000での変数の格納方式について説明があった。 今回,それを基に変数の格納方式を調査し,上記の解説で誤った個所を訂正したものも説明する。


2-1. BASICの隠し命令

 2つの隠し命令が見つかった。
MODE命令
 文法は,
      MODE 引数1(引数2) で,引数1の値によって機能が分かれる。
  10, 11: PJ 1991年7月号の『FX-870P解析詳細』では不明だったが,MODE10で四則演算後に丸め処理を行い,MODE11で丸めを行わないようになる。
  110: BANK1にある機械語プログラムをCALLする。引数2はアドレス。
  200,201: FDのセクタのREAD,WRITE命令。引数2は(トラック, サーフェイス, セクタ)で,トラックは0-79, サーフェイスは0-1,セクタは1-8である。どちらがREADかは不明。

CALCJMP命令
 引数なしの命令で,CALCキーを押したのと同じで,INキーで入力した計算式を実行する。 ただし,CALモードでしか実行できず,BASICモードではFCerrorとなる。




2-2. BASICプログラムおよび(テキスト)ファイルの格納形式

 P0~F9のプログラムおよびC, CASLのソースファイルを格納できる(テキスト)ファイルエリアのファイルは,システムエリアのP0STT~F9STTに それぞれのデータの格納される先頭番地が格納されている。プログラム(BASIC)の終端コードは00H,ファイルの終端コードは1AHであり,どちらも最低1バイトは消費し, 全部で20バイトは消費するようになっている。また,VX-4のマニュアルではファイルエリアから全21バイトが引かれたものをユーザーエリアとしており,メモリの最後の1バイトは消費 されないようである。ファイルの終端コード 1AH は,多くのOSでファイルの終端コード(EOF; End Of File)として使われていて有名である。
 また,各ファイルの間に,無駄なデータが発生しないように,メモリー・ブロック転送とP1STT~MEMENの変更をシステムが自動的に行っている。 ただし,P0STTはユーザーがCLEAR文等を行わない限り変更されず,システム側が勝手に変更することはない。

 プログラムエリアのP0~P9には,BASICのプログラムが格納され,BASICのプログラム方式はPB-100と全く同じ。 リスト5のBASICサンプル・プログラムは,表7のように格納される。 各行は,行の長さ(1byte), 行番号(2byte), スペース(1byte), BASICコード(可変長),行終端コード(1byte)で構成される。 行の長さは,行番号~行終端コードの総バイト数で,これが0の場合,プログラムの終了を表す。行番号は,リトル・エンディアンの2バイトである。 スペースは,行番号とBASICコードの間にある空白であり,&H20で固定。BASICコードは,予約語がビッグ・エンディアンの2バイトの内部コードに変換された文字列である。 予約語には,処理先ありと関数のように処理先のない予約語があり,それぞれ表8, 9にそれぞれの内部コードを示す。行終端コードは0で固定である。

リスト5. BASICサンプル・プログラム
100 REM Sample
110 ' Program
120 CLS
130 PRINT"Hello"
140 END
150 'dummy dummy dummy dumy dummy dummy



表7. リスト5 のメモリ内容
LEN
1byte
LNUM
2bytes
SPC
1byte
Program Statement
Variable Length
EOL
1byte
0D
13
64 00
100
20
 
04 A9
REM
20
 
53
S
61
a
6D
m
70
p
6C
l
65
e
00

0D
13
6E 00
110
20
 
02
'
20
 
50
P
72
r
6F
o
67
g
72
r
61
a
6D
m
00

06
6
78 00
120
20
 
04 71
CLS


00

0D
13
82 00
130
20
 
04 A3
PRINT
22
"
48
H
65
e
6C
l
6C
l
6F
o
22
"
00

06
6
8C 00
140
20
 
04 87
END


00

00
0



表8.処理先アドレス付き内部コード
CODE BASIC コマンド 処理先
 0449H  GOTO 368AH 
 044AH  GOSUB 3620H 
 044BH  RETURN 3663H 
 044CH  RESUME 3ACBH 
 044DH  RESTORE 42EBH 
 044EH  WRITE# 5517H 
 0450H  CONT 35ADH 
 0452H  SYSTEM 51BAH 
 0453H  PASS 525CH 
 0455H  DELETE 3CDDH 
 0457H  LIST 3D26H 
 0458H  LLIST 3D21H 
 0459H  LOAD 4753H 
 045AH  MERGE 474BH 
 045CH  RENUM 43DAH 
 045DH  TRON 3617H 
 045FH  TROFF 3614H 
 0460H  VERIFY 474FH 
 0463H  POKE 3A23H 
 0469H  CHAIN 4762H 
 046AH  CLEAR 53A8H 
 046BH  NEW 4594H 
 046CH  SAVE 4736H 
 046DH  RUN 352CH 
 046EH  ANGLE 3929H 
 046FH  EDIT 58B8H 
 0470H  BEEP 43C7H 
 0471H  CLS 2ADFH 
 0472H  CLOSE 46B0H 
 0476H  DEF 397DH 
 0478H  DEFSEG 3A3AH 
 047CH  DIM 3A4AH 
 0480H  DATA 0B9BH 
 0481H  FOR 36F9H 
 0482H  NEXT 383BH 
 0485H  ERASE 3A81H 
 0486H  ERROR 2BA8H 
 0487H  END 3520H 
 048BH  FORMAT 7F0FH 
 048DH  IF 38BBH 
 048EH  KILL 7F1EH 
 048FH  LET 2EA2H 
 0490H  LINE 3E26H 
 0491H  LOCATE 39FAH 
 0496H  NAME 7F35H 
 0497H  OPEN 45DFH 
 0499H  OUT 2BA8 
 049AH  ON 3B71H 
 049FH  CALCJMP 542CH 
 04A3H  PRINT 3EF1H 
 04A4H  LPRINT 3EECH 
 04A5H  PUT 2BA8H 
 04A8H  READ 42A0H 
 04A9H  REM 0B9BH 
 04ACH  SET 532AH 
 04ADH  STAT 4322H 
 04AEH  STOP 3500H 
 04B0H  MODE 52A2H 
 04B2H  VAR 3BEBH 
 04B5H  FILES 7F87H 
表9.処理先なし内部コード
CODE BASIC 関数 
 054FH  ERL
 0550H  ERR
 0551H  CNT
 0552H  SUMX
 0553H  SUMY
 0554H  SUMX2
 0555H  SUMY2
 0556H  SUMXY
 0557H  MEANX
 0558H  MEANY
 0559H  SDX
 055AH  SDY
 055BH  SDXN
 055CH  SDYN
 055DH  LRA
 055EH  LRB
 055FH  COR
 0560H  PI
 0561H  DSKF
 0563H  CUR
 0567H  FACT
 0569H  EOX
 056AH  EOY
 056BH  SIN
 056CH  COS
 056DH  TAN
 056EH  ASN
 056FH  ACS
 0570H  ATN
 0571H  HYPSIN
 0572H  HYPCOS
 0573H  HYPTAN
 0574H  HYPASN
 0575H  HYPACS
 0576H  HYPATN
 0577H  LN
 0578H  LOG
 0579H  EXP
 057AH  SQR
 057BH  ABS
 057CH  SGN
 057DH  INT
 057EH  FIX
 057FH  FRAC
 0581H  DEGR
 0582H  DMS
 0586H  PEEK
 058AH  EOF
 058DH  FRE
 0590H  ROUND
 0592H  VALF
 0593H  RAN#
 0594H  ASC
 0595H  LEN
 0596H  VAL
 059BH  HYP
 059CH  DEG
 05A7H  REC
 05A8H  POL
 05AAH  NPR
 05ABH  NCR
 05ACH  HYP
 0697H  DMS$
 069BH  INPUT
 069CH  MID$
 069DH  RIGHT$
 069EH  LEFT$
 06A0H  CHR$
 06A1H  STR$
 06A3H  HEX$
 06A8H  INKEY$
 0747H  THEN
 0748H  ELSE
 07B6H  TAB
 07BBH  ALL
 07BCH  AS
 07BDH  APPEND
 07C0H  STEP
 07C1H  TO
 07C2H  USING
 07C3H  NOT
 07C4H  AND
 07C5H  OR
 07C6H  XOR
 07C7H  MOD
(注)



 ファイルエリアのF0~F9は汎用ファイルであり,C,CASLのソースファイルや,BASIC等で計算結果の入力・出力先に利用できる。 そのデータ格納形式はMS-DOS等の一般的なOSと全く同じ。 例えば,リスト6 のファイルは,表10のようにメモリに格納されている。改行コードは,ODH, 0AH,ファイル終端コードは,1AH で,MS-DOSと全く同じである。

 なお,プログラムおよびファイルエリアを調べるプログラム B-1. CHKPFAV4.BASのリストを示しているので, これを使えば自分でこの節の内容を確認することができる。

リスト6.
サンプル・ファイル
HELLO,WORLD!         
表10. リスト6のメモリ格納形式
Data
48
H
45
E
4C
L
4C
L
4F
O
2C
,
57
W
4F
O
52
R
4C
L
44
D
21
!
0D
CR
0A
LF
1A
EOF




2-3. 変数データの格納形式

 プログラムの実行・CALモード等で変数を使ったとき,変数テーブルにまだ登録されていない,すなわち,初めて使った数値変数・文字変数は,BASICのシステムによって自動登録され,実体化される。 また,配列変数はBASICシステムが自動的に実体化できず,DIM文でユーザーが意図的に宣言して実体化させる必要がある(恐らく,無駄なメモリ消費防止のため)。 以上のようにして,BASICのワークエリアに実体化・格納された状況を図3 に示す。


図3. FX-870P / VX-4 のRAMメモリーマップ(BASIC時)


 図3で,青色で書かれたRAM先頭の3個の数字は固定値である。赤色で書かれた IOBF, TOSDT, P0STT, DIRENは ユーザーが設定可能な値であり,BASICが自分で勝手には変更できない数値である。 1CD0H~(IOBF - 1)は機械語領域であり,IOBFは通常は変更できず1CD0Hで機械語領域は0byteであるが,拡張CLEARなどで変更して機械語領域を確保できる。 P0STT, TOSDTTは,BASICのCLEAR文で設定でき,(P0STT - IOBF)がワーク領域サイズ, (P0STT - TOSDT)が変数領域サイズで,実際には文字変数・配列文字変数の格納される領域である。 DIRENは,FX-870P / VX-4 の持つRAM の最終アドレスで,通常変更することはない。 通常1バイトであるが,DIRENを変更して数バイト分空きを作れば,ゲームのハイスコアの記憶等に利用できる。 機械語領域はC言語モードでC のプログラムを実行すると内容が破壊されるが,DIREN以降の領域のデータは破壊を免れるようである。
 このとき,BASIC システムは,IOBFからI/Oバッファ,文字演算スタックにメモリを使用し, TOSDTから変数テーブル,数値変数・配列数値変数のデータエリア,GOSUBスタック,FORスタックとしてアドレス逆方向に利用する。 最後に,TOSDTからアドレス順方向に文字変数・配列文字変数のデータエリアとして利用する。
 変数の格納形式について,基本的なことは Jun Amano氏が既に説明している(文献(13))。 今回,変数の格納形式の情報を完全なものとするため,ワークエリアの変数格納状態をファイルに出力するプログラム B-2. OUTWRKV4.BAS を用いて,解析した結果を述べる。
 このプログラムによって,実体化された変数の格納形式を解析した結果を表11~13に示す。
 変数テーブルは,DTTBに格納されたアドレスから順方向に検索するようになっている。データのアドレスは,(DTTB)~(TOSDT)-1である。変数テーブルのデータ・フォーマットは,変数属性(1バイト),変数名の文字数(1バイト), 変数名(可変長),実際にデータを格納するポインタ(2バイト)であり,次の変数には(現在検索中の変数属性のアドレス)に(現在の検索中の変数の文字数) + 4を加えればよい。 また,変数は実体化された変数とは逆順に検索するようになっており,最後に実体化した変数が最初に検索でヒットされるようになっている。 変数属性は,文字変数,数値変数,配列文字変数,配列数値変数の4種類で,それぞれ 20H, 28H, A0H, A8Hである。 そのため,A$, A, A$(), A() と同じ変数名で4つの変数種類が同時に存在することが可能になっている。
 数値データエリアは,(TONDT)~(DTTB)-1 のアドレスのエリアであり,数値変数・配列変数のデータが格納される。 基本的に数値データはパックト・リトルエンディアン符号化されたBCD浮動小数点フォーマットで格納されているが, 配列変数の場合,変数テーブルのポインタは,配列数値変数の宣言情報を指している。最初の1バイトが,配列変数の次元, そこから2バイトずつ各添字の最大値が配列次元個並んでいる。 2次元以上の多次元配列変数はBASICシステム内部では添字を1次元化して管理しなければならないが,一番右の添字がループの一番内側に来るように一元化する。 すなわち,DIM A(MN, MN-1, ・・・, M1)と宣言した場合,A(In, In-1, ・・・, I1)と表記した配列数値変数の一要素の添字は, 内部では,

    

という式で添字が一元化されていると考えれば良い。また,配列数値変数は,数値データエリアにDIM分で宣言した通りのデータ格納域を確保した後(初期値 0), 基本的にメモリサイズの変更はないので,BASICのシステム管理は文字配列変数と比較して楽である。
 文字変数データエリアは,(TOSDT)~(PTSDT)-1のアドレスのエリアであり,文字変数・配列文字変数のデータが格納される。 文字変数の場合,変数テーブルのポインタの指す最初の1バイトは,変数に格納されたデータの文字数であり,その文字数数の文字列データが続いて格納されている。 配列文字変数の場合,配列数値変数と同じく,配列数値変数の宣言情報が入っている。 ただし,多次元配列の内部での一次元化は数値配列変数と同じであるが,数値配列変数は各データが8バイトなのに対して文字変数は可変なため, 内部一次元の添字を0から検索して目的の添字まで到達しなければならず,配列数値変数よりアクセスが非効率である。  また,文字データの代入,削除(""の代入)によって,文字変数データエリアに不必要なデータが残ることはなく,BASICのシステムが自動的にメモリ管理を行っている。 すなわち,文字変数または配列文字変数のデータを変更して,文字変数データエリアのサイズ変更の必要が発生すると,その変数より後に実体化した (配列変数の場合,内部で一次元化した添字で大きい添字)のデータを必要分シフトさせて,変数テーブルのポインタもシフト分ずらす作業を行っている。 したがって,最後に実体化した文字変数(文字配列変数)ほど,文字変数の代入によるBASICシステムの負荷は小さい。
 また,CLEARでワークエリアの内容を0にするのでなく,各ポインタの変更だけをしている。変数の初期化は,変数テーブルに変数が登録されるときに行われる。

 以上の解析結果をまとめると,以下の通り。
変数のメモリ使用量は,表14 のようになる。

表14. 変数の使用メモリ量
変数の種類変数テーブル使用量 (byte)データ格納先データ格納サイズ (byte)
数値変数(変数名の文字数)+4数値データエリア8
配列数値変数1+(次元数)×2+(配列要素数)×8
文字変数文字変数データエリア(代入した文字列の文字数)+1
配列数値変数1+(次元数)×2+(配列要素数)+(全配列要素で代入した文字列の文字数)


また,BASICの高速化には,以下の注意点が有効。


表11. 変数テーブル(DTTB) 解析結果
Address
(16進)
変数テーブル・データ
属性
1byte
文字数
1byte
変数名
Variable Length
ポインタ
2byte
3A8A2001 53EF3A
Ch01S3AEF
3A8F2803 535430ED39
Nu03ST0 39ED
3A962802 4E58F539
Nu02NX 39F5
3A9C2802 5354FD39
Nu02ST 39FD
3AA22802 4144053A
Nu02AD 3A05
3AA82001 46ED3A
Ch01F 3AED
3AAD2801 4A0D3A
Nu01J 3A0D
3AB22801 49153A
Nu01I 3A15
3AB7A003 515745D63A
AC03QWE 3AD6
3ABEA803 504F491D3A
AN03POI 3A1D
3AC52002 4243D03A
Ch02BC 3AD0
3ACB2801 41823A
Nu01A 3A82
(注)
属性のCh, Nu, AC, AN は, それぞれ,文字変数,数値変数,配列文字変数,配列数値変数を表す。


表13. 文字変数データ (TOSDT) 解析結果
Address
(16進)
TOSDT データ備考
3AD0 05434153 494F BC$ の値。最初の1バイトは文字数。
5"CASIO"
3AD6 010500 配列文字変数 QWE$( )のDIM文 DIM QWE(5)で宣言した情報。
最初の1バイトが次元。2バイトずつ,添字の最大値を定義。
15
3AD9 00 QWE$(0) の値
""(no data; null)
3ADA 06504F43 4B4554 QWE$(1) の値。
6"POCKET"
3AE1 00 QWE$(2) の値
""(no data; null)
3AE2 08434F4D 5055544552 QWE$(3) の値。
8"COMPUTER"
3AEB 00 QWE$(4) の値
""(no data; null)
3AEC 00 QWE$(5) の値
""(no data; null)
3AED 0130 F$ の値
1"0"
3AEF 00 S$(4) の値
""(no data; null)
(注)
本プログラムで出力されるS$に関するデータは0でない(32Hであった)。 これは,S$はプログラム動作中ファイル出力のため,頻繁に変化するためである。 この表ではプログラム終了後の値を調べて,データを修正している。
また,S$の影響を最小限に抑えるよう,プログラムに工夫が施してある。
表12. 数値データエリア (TONDT) 解析結果
Address
(16進)
変数テーブル・データ備考
39ED 00000000 16484110 ST0 の値
14816
39F5 00000000 86494110 NX の値
14986
39FD 00000000 29484110 ST の値
14829
3A05 00000000 86494110 AD の値
14986
3A0D 00000000 00000310 J の値
3
3A15 00000000 73484110 I の値
14873
3A1D 02020003 00 配列数値変数 POI( )のDIM文 DIM POI(2,3)で宣言した情報。
最初の1バイトが次元。2バイトずつ,添字の最大値を定義。
223
3A22 00000000 00000000 POI(0,0) の値
0
3A2A 00000000 00000166 POI(0,1) の値
-1E60
3A32 00000000 00000266 POI(0,2) の値
-2E60
3A3A 00000000 00000000 POI(0,3) の値
0
3A42 00000000 00000466 POI(1,0) の値
-4E60
3A4A 00000000 00000566 POI(1,1) の値
-5E60
3A52 00000000 00000666 POI(1,2) の値
-6E60
3A5A 00000000 00000000 POI(1,3) の値
0
3A62 00000000 00000866 POI(2,0) の値
-8E60
3A6A 00000000 00000966 POI(2,1) の値
-9E60
3A72 00000000 00001166 POI(2,2) の値
-1E61
3A7A 00000000 00000000 POI(2,3) の値
0
3A82 20018967 45230110 A の値
1.234567890120



P.S.
Jun Amano氏のHPがなければ,ここまで変数の格納形式を理解できなかったので,ここで感謝します。






A. 付録資料

A-1. PB-1000 のメモリ・マップ


図A1. PB-1000 メモリ・マップ

 カシオ PB-1000のメモリ・マップを図A1 に示す(文献(11))。 8000H~FFFFHのアドレス空間のバンクを切り替えることで,BANK 0のシステムROMとBANK 1のRAM(増設RAM)にアクセスするようになっている。 また,0000Hか~7FFFHは,他にバンク指定してもBANK 1しかアクセスできない仕様になっており,BANK 1~3のアドレス0000H~7FFFHにはアクセスできない。



A-2. BCD 浮動小数点フォーマットと内部形式

 カシオのポケコンは,論理演算などの一部を除いて,数値計算はBCD浮動小数点データで計算を行い, 全ての数値変数・配列数値変数はBCD 浮動小数点データとして格納されている。 PB-1000のBCD 浮動小数点フォーマットと内部格納形式は,ポーランドのPiotor Piatek氏によって説明されている(文献(14))。 しかし,説明不足なところもあり理解しにくいところもあるので,ここで説明する。
 まず,結論を言うと,数値データのデータ格納形式は,

  1. カシオのBCD 浮動小数点フォーマット(BCD floating-point data format),
  2. リトルエンディアンによる符号化(Little endian encoding),
  3. パックト・リトルエンディアン(Packed little endian encoding)
の順で理解すると,理解しやすい。


図A2. BCD 浮動小数点データ・フォーマット (カシオ)


 FX-870P / VX-4では,数値データは符号付きの仮数部13桁,符号付きの指数部2桁の正規化10進指数が基本フォーマットとなる。すなわち,
    (msgn)(m0) . (m1)(m2) ・・・ (m11)(m12)×10(esgn)(E1)(E0)
と表現される。ここで,(msgn),(esgn)はそれぞれ仮数部(Mantissa part),指数部(Exponetial part)の符号で,+または-である。 他は,0~9の数字で,指数部は2桁であり,仮数部は正規化されているので,1.000,000,000,000~9.999,999,999,999である。 この規則に従えば,
    +1.123456789012 × 10 -25
のような数字が作れる。なお,0は全て0とすることで,0を表現する。
 この数字を,9バイトの18ディジットでBCD(Binary-Coded Decimal)表記する。このとき,MSD(Most Siginificant Digit)は0で, 次の 3桁(ss)(e1)(e0)は仮数部の符号と指数部を一体としてまとめたもの(両符号・指数混合部),次の桁が仮数部キャリー(mc)で通常0, 残りの13桁が仮数部(m0) . (m1)(m2) ・・・ (m11)(m12)である。仮数部は元の数値そのままなので,問題ないが,両符号・指数混合部は以下のように与えられる。
 両符号・指数混合部(ss)(e1)(e0)は まず10進 3桁の数字と考え,指数部に +100してオフセットすることを基本とし,仮数部の符号が マイナス(-)の場合に限って, 更に +500すると考えれば良い。
例えば,指数部(esgn)(E1)(E0) = -25,仮数部符号(msgn) = + ならば,
    (ss)(e1)(e0) = -25 + 100 = 075,
指数部(esgn)(E1)(E0) = +25,仮数部符号(msgn) = - ならば,
    (ss)(e1)(e0) = +25 + 100 + 500 = 625
となる。
 ここで +500である理由は,乗除算において仮数部の符号計算も指数の加減算と同時にできるようにするためと推測される。 例えば,-同士を掛ける時,500と500が足されて1000となり,仮数部の符号が + になることを同時に求められる。

 以上の説明で BCDC浮動小数点フォーマットで数を符号化できる。例えば,-1.123456789012×10 -29は,BCD浮動小数点フォーマットでは,
    05 71 01 12 34 56 78 90 12
となる。

 BCD浮動小数点フォーマットが理解できれば,後は,CPUの問題となる。FX-870P / VX-4のCPU HD61700は,リトルエンディアン方式なので, メインレジスタへのロードは最下位バイトから昇順で行われる。例えば,先ほどの05 71 01 12 34 56 78 90 12は,$0から$8へは
    12 90 78 56 34 21 01 71 05
とロードされる。 このレジスタへのロード状態が,Piotr Piatek氏のBCDフォーマットの最初の説明であり,本来のBCD浮動小数点フォーマットを明示していないため,メモリ格納形式であるパックト・リトルエンディアン符号化状態が分かりにくくなっている。
 本来のBCD浮動小数点フォーマットにおいて MSDと(mc)が0なので,(e0)を(mc)に移動させて,(ss)(e1)を1桁上へシフトさせて1バイト削減させるのが,パックト・リトルエンディアン符号化で, メモリにはこの方式で格納されている。
例えば,リトルエンディアン符号化されたデータ 12 90 78 56 34 21 01 71 05 (数値: -1.123456789012 × 10 -29)は,メモリ内には
    12 90 78 56 34 21 11 57
と格納されている。
図B2で見ると,パックト・リトルエンディン符号化において桁の移動が複雑で理解しにくいように見えるが,本来のBCD 浮動小数点フォーマットで考えれば,自然な桁の移動であることが分かる。 実際,この操作は,$0, $1, ・・・, $8に浮動小数点データが格納されている場合,
    DIUW $7 ;Digit Up of ($8, $7) pair
OR $6, $7 ;$6 <- $6 or $7, where the upper digit of $7 and the lower one are equal to (e0) and zero respectively.
LD $7, $8 ;$7 <- $8
で圧縮できる。また,逆にメモリから$0~$7にロードされた圧縮された数値データは,
    LD $8, $7 ;$8 <- $7
LD $7, $6 ;$7 <- $6
DIDW $8 ;Digit Down of ($8,$7)
AN $6,&H0F ;clear the upper digit of $6
で元の状態を実現でき,合理的である。
 後継機のFX-890P / Z-1のCPUも x86系の80186でリトルエンディアン方式のCPUであり,メモリ内での格納形式は同じである。
 FX-870P / VX-4で数値データの内部格納形式を16進表示するプログラムをB-3で用意しているので,メモリ格納形式を自分で確かめることができる。

 図A2 の一番下には,Piotr Piatek氏がHPで説明している,PB-1000での数値データのスタックでの配列を示している。 彼は事実だけで理由を述べていないが,このスッタック配列はHD61700 特有の理由による。 BCD 浮動小数点データのある$0~$8をユーザースタックに退避させる場合,マルチバイトのPUSHを使うと高速化できるが,最大 8バイト分しかサポートされていない。 そのため,1バイトは別にプッシュする必要がある。そこで,
    PHUM $7, 8 ;PushH User-stack Multibyte for ($7,・・・,$0)
PHU $8 ;PusH User-stack for $8
と実行すれば,図のようにユーザースタックに退避される。なお,退避したデータをポップするには,
    PPU $8 ;PoP User-stack for $8
PPUM $0, 8 ;PoP User-stack Multibyte for ($7,・・・,$0)
とすれば良い。ここで,DIUWとDIDW,PHUMとPPUMで,レジスタ番号が違う。これも,HD61700 特有の仕様である。 また,パックト・リトルエンディン符号化されたデータを復元する際,最初の2命令を
    LDW $7, $6 ;($8,$7) <- ($7,$6)
と出来れば良いが,$7←$6, $8←$7 と実行されてしまって,最上位バイトの$8まで$6がコピーされて,目的の動作が達成されない。
最後に,ユーザースタックにプッシュする際,
PHU $8 ;PusH User-stack for $8
    PHUM $7, 8 ;PushH User-stack Multibyte for ($7,・・・,$0)
と,最初に$8をプッシュするようにすれば,スタックの低アドレス側から$0, $1, ・・・, $7, $8 と通常の並びで詰めるのであるが, なぜそうしないのか不思議であり,また,FX-870P,VX-4でもPB-1000の作法を継続しているかは,現在,未解析なため不明である。


P.S.
Piotr Piatek氏のHPがなければ,ここまでBCD浮動小数点フォーマットを理解できなかったので,ここで感謝します。






B. BASIC プログラム

 今回,FX-870P / VX-4 の内部情報を独自に調べるため,幾つかのプログラムを作って調査を行った。 以下に,主要なプログラムのリスト,プログラムの簡単な解説と使い方を説明する。 このようなプログラムは,本来,不必要であるが,ファイルへの出力など,一部,参考になるだろう。


B-1. CHKPFAV4.BAS : プログラムエリアとファイルエリアをチェックする

リスト B-1. CHKPFAV4.BAS
100 ' CHKPFAV4.BAS
110 '  check program and file area
120 '
130 '  for FX-870P/VX-4
140 '
150 '  programmed by 123
160 '  since 30th, Oct., 2010.
170 '
190 '
200 INPUT "1:disp addrs, 2:disp one of P0-F9";MD
210 IF MD=2 THEN GOSUB 500 ELSE GOSUB 300
220 END
290 '*DISPADR:'disp addrs
300 POI=&H18A7:'addr of P0
310 PRINT "Addresses of P0-F9"
320 FOR I=0 TO 9
330   AD=POI:GOSUB 1000
340   PRINT "P";RIGHT$(STR$(I),1);":";HEX$(AD);" ";
350   POI=POI+2
360 NEXT
370 PRINT
380 FOR I=0 TO 9
390   AD=POI:GOSUB 1000
400   PRINT "F";RIGHT$(STR$(I),1);":";HEX$(AD);" ";
410   POI=POI+2
420 NEXT
430 'PRINT
440 AD=POI:GOSUB 1000
450 PRINT "MEMEN:";HEX$(AD)
460 RETURN
490 '*DISDAT:'disp data of PF area
500 INPUT "Input any one of P0-F9";FL$
510 POI=-1:QWE$=LEFT$(FL$,1)
520 IF QWE$="P" OR QWE$="p" THEN POI=0
530 IF QWE$="F" OR QWE$="f" THEN POI=1
540 IF POI<0 THEN PRINT "Illegal 1st letter!":END
550 AD=&H18A7+20*POI
560 POI=-1:CD=ASC(RIGHT$(FL$,1))
570 IF CD>=&H30 AND CD<=&H39 THEN POI=CD-&H30
580 IF POI<0 THEN PRINT "Illegal 2nd letter!":END
590 AD=AD+2*POI
600 POI=AD
610 GOSUB 1000:ST=AD
620 AD=POI+2
630 GOSUB 1000:NX=AD
640 PRINT FL$;":";HEX$(ST)
650 GOSUB 1100
660 END
990 '*GETAD:'get address
1000 AD=PEEK(AD)+PEEK(AD+1)*256
1010 RETURN
1090 '*OUTHEX
1100 ST0=ST AND &HFFF0
1110 S$=""
1120 FOR I=ST0 TO NX-1
1130   IF (I AND &HF)=0 THEN S$=HEX$(I)+":"
1140   IF I>=ST THEN S$=S$+" "+RIGHT$(HEX$(PEEK(I)),2) ELSE S$=S$+"   "
1150   IF (I AND &HF)=15 OR I=NX-1 THEN PRINT S$:S$=""
1160 NEXT
1170 'PRINT
1180 RETURN
1190 ' end of program

 システムエリアのP0STT~F9STT, MEMEN の格納するアドレスを調べて表示,または,プログラム・ファイルの内容を16進表示する。 ファイル出力させると,その行為がF0STT~F9STTの内容に影響を与えてしまうため,LCD表示で済ませている。  これによって,プログラム,(テキスト)ファイルの格納形式を調べられる。



B-2. OUTWRKV4.BAS : ワークエリアの変数格納状態をファイルに出力する

リスト B-2. OUTWRKV4.BAS
100 ' OUTWRKV4.BAS
110 '  output data of work area of FX-870P/VX-4
120 ' to File F0-9
130 ' for FX-870P/VX-4
140 '
150 ' programmed by 123
160 ' since 30th, Oct., 2010.
170 '
180 ' S$ must be emobodied at lat for string data stability!!
190 '
200 ' Data input
210 A=1.23456789012
220 BC$="CASIO"
230 DIM POI(2,3)
240 DIM QWE$(5)
250 FOR I=0 TO 2
260   FOR J=0 TO 2
270     POI(I,J)=(I*4+J)*(-1E60)
280   NEXT
290 NEXT
300 QWE$(1)="POCKET"
310 QWE$(3)="COMPUTER"
320 F$="0":AD=0:ST=0:NX=0:ST0=0:S$=""
490 ' Output work area to F0...9
500 INPUT "Output FileNumber";F$
510 RESTORE#("F"+F$)
520 WRITE#:'clear file
530 WRITE#"WORK AREA DATA"
540 ' TONDT(&H189F):numerical data
550 AD=&H189F:GOSUB 1000:ST=AD
560 AD=&H18A1:GOSUB 1000:NX=AD
570 WRITE#"TONDT:numerical data"
580 GOSUB 1100
590 ' DTTB(&H18A1):variable table
600 ST=NX
610 AD=&H18A3:GOSUB 1000:NX=AD
620 WRITE#"DTTB:variable table"
630 GOSUB 1100
640 ' TOSDT(&H18A3):string data
650 ST=NX
660 AD=&H18A5:GOSUB 1000:NX=AD
670 WRITE#"TOSDT:string data"
680 GOSUB 1100
690 ' PTSDT(&H18A5):free area of string
700 ST=NX
710 AD=&H18A7:GOSUB 1000:NX=AD
720 WRITE#"TOSDT:free area of string"
730 GOSUB 1100
740 END
990 '*GETAD:'get address
1000 AD=PEEK(AD)+PEEK(AD+1)*256
1010 RETURN
1090 '*OUTHEX
1100 ST0=ST AND &HFFF0
1110 S$=""
1120 FOR I=ST0 TO NX-1
1130   IF (I AND &HF)=0 THEN S$=HEX$(I)+":"
1140   IF I>=ST THEN S$=S$+" "+RIGHT$(HEX$(PEEK(I)),2) ELSE S$=S$+"   "
1150   IF (I AND &HF)=15 OR I=NX-1 THEN WRITE# S$:S$=""
1160 NEXT
1170 WRITE#
1180 RETURN
1190 ' end of program

 システムエリアのTONDT~P0STTの格納するアドレスを調べて,数値データ領域,変数テーブル,文字変数データ領域, 文字変数データをファイル(F0-F9)に16進出力する。 プログラム上のコメントとしては,以下の通り。

プログラムの動作方法としては,以下の2通り。



B-3. CHKAV4.BAS : 数値変数 A の数値データをバイナリ表示する(BCD浮動小数点フォーマット調査用)

リスト B-2. CHKAV4.BAS
100 ' CHKAV4.BAS
110 '   check A, numerical variable
120 '     to inspcet the inner represenation
130 '   for FX-870P,VX-4
140 ' programmed by 123
150 ' since 28th,Oct.,2010
200 AD=&H18A1
210 DTTB=PEEK(AD)+PEEK(AD+1)*256
220 AD=&H18A3
230 TSDT=PEEK(AD)+PEEK(AD+1)*256: 'TOSDT
240 '
250 FOR AD=DTTB TO TSDT-1
260   IF PEEK(AD)=&H28 AND PEEK(AD+1)=1 AND PEEK(AD+2)=&H41 THEN 310
270 NEXT
280 PRINT "Failed to find var A!"
290 END
300 '
310 AD=PEEK(AD+3)+PEEK(AD+4)*256
320 PRINT "A= ";A
330 FOR II=0 TO 7
340   PRINT RIGHT$(HEX$(PEEK(AD+II)),2);" ";
350 NEXT
360 PRINT
370 END
380 ' end of program


 システムエリアのDTTB~TOSDTの変数テーブルを調べて,数値変数 Aの値の内部形式を16進で出力する。 これによって,数値変数のメモリへの格納形式を確認できる。
 なお,FX-870P / VX-4の後継機のFX-890P / Z-1 では,Aは固定変数であるため(『Z-1/FX-890P活用研究』 ),変数テーブルを調べずに,固定したアドレスの内容を出力するだけなので, プログラムは単純である。参考のため,FX-890P /Z-1用の同等プログラムをリスト B-3 に示す。 ここで,FOR ~NEXTループで変数にIでなく,IIを使っているのは,元のプログラムが,Aだけでなく,A~Zまでの変数を対象にしていたので,Iを使えなかったからである。

リスト B-3. CHKAZ1.BAS (FX-890P / Z-1 用)
100 ' CHKAZ1.BAS
110 '   check A, numerical variable
120 '     to inspcet the inner represenation
130 '   for FX-890P,Z-1
140 ' programmed by 123
150 ' since 28th,Oct.,2010
200 AD=&H196F
210 PRINT "A= ";A
220 FOR II=0 TO 7
230   PRINT RIGHT$(HEX$(PEEK(AD+II)),2);" ";
240 NEXT
250 PRINT
260 END
270 ' end of program





参考文献








123