パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)

DUMPプログラム作成  (互換/(一般))

==========================================
どのプログラム言語でも、プログラム入門書なるものを見ると、本の最後の方に、一通りの文法を
学んだあとのおさらいとして、「DUMPプログラム」の作成が課題としてとりあげられています。
とりあえず、DUMPプログラムが一人で作成できれば、入門卒業として考えていいかもしれません。

DUMPプログラムを作成するには
・ファイルのオープン、クローズ、データの入出力
・キーボードからの入力と入力値の処理
・モニターへの表示、成型した出力(ゼロパッティングなど)
・条件判断と分岐
など、プログラム作成に必要な技法を一通り使います。DUMPプログラムが作成できれば、簡単なゲーム
などは容易に作れるでしょう。

というわけで、DUMPプログラムの作成をしてみましょう。ちなみに今回は、N88互換Basic for Win
を対象に作成しましたが、一般的なBasicでほとんど手直しなしで、移植できると思います。
N88互換Basic for Win では、field , get といったランダムファイルアクセス系の命令が若干オリジナル
仕様(旧BasicよりVisual Basicよりで、柔軟な仕様)になっていますが、今回のDumpプログラムでは
オリジナル仕様の使い方ではなく、ごく一般的な使い方ですので、コードはそのままでO.K.だと思います。
もし、エラーが出るようであれば、お使いのBasicの文法仕様を確かめて、アレンジして下さい。

なお、ほぼ同様の機能を持ったDUMPプログラムをアセンブラで組んだものを、姉妹サイトの
パソコン活用研究ラピュタへの道/DUMPプログラム作成 コード編」で解説しています。興味が
あればのぞいてみてください。
==========================================

1 DUMPプログラムの仕様について

プログラムの流れは以下の通りです
(1) ダンプしたいファイル名の入力
(2) コマンドの入力。コマンドは以下の通り。
  D ダンプ開始   Q プログラム終了   C バイナリーデータ検索
  Cコマンドの検索で指定したデータは赤色で表示します。
  Cコマンド指定例  &H5Eを検索データとして指定する場合 -C5E と記述します
(3) Dコマンドによるダンプ中にはサブコマンドが使えます。
  サブコマンド 1 一時中断   2 再開    3 コマンド入力に戻る

下記は実行中の画面例です。Cコマンドで"0D"を指定しているので、0Dは赤色で表示されて
います。



2 プログラム概説
(1) 初期設定
コードに関しては、特に説明するところはありませんので、このプログラムで使っている変数に
について解説します。

50行目は、開発中の遺産です。ファイルをオープンするプログラム開発中に、プログラムのバグで
プログラムが終了すると、ファイルがクローズされない(オープンのまま)状態で残ってしまうことが
あります。そのため、プログラムの最初に、こんなおまじないを入れて開発したりしますが、その時
の残りです。削除して構いません。

60、70行目で変数の、宣言、初期化をしています。
b$ 読み込んだデータの一時保存用に使います
n  ランダムファイル読み込み時のレコード番号
address ダンプ表示時のアドレス
frag 0 ダンプ中   1 ダンプ一時中断中
kan2 1 漢字の2バイト目のデータの可能性がある

10 ' File Dump Ver 0.0.2 for N88互換Basic
20 '
30 '初期設定
40 on error goto 590
50 cls:close:
60 dim b$(17)
70 n=1:address=0:frag=0:kan2=0
80 print "File Dump ver0.0.1 for N88互換BASIC for Win";
90 print " Written by Kasayan86"
100 print"***コマンド***"
110 print "D ダンプ開始 Q プログラム終了 C バイナリーデータ検索 指定したデータは赤色で表示"
120 print "Cコマンド指定例 &H5Eを検索データとして指定する場合 -C5E と記述して下さい"
130 print "ダンプ中のサブコマンド 1 一時中断 2 再開 3 コマンド入力に戻る"

(2) ファイルオープン、コマンド入力

180行 ランダムファイルを開く時の、open の使い方です。(=ランダムモード)
ランダムモードでファイルを開くと、ファイルの好きな位置にアクセスして、データを取得することが
できます。

190行 c$=left$(cmnd$,1)
"-"に続けて入力されたコマンドをc$に抜き取ります

720行からはCコマンドの処理用サブルーチンです
720行 c1$=mid$(cmnd$,2,2)
"-"に続けて入力されたCコマンド文字列(=cmnd$)の2文字目から、2文字取り出して、c1$に入れます
例えば、"-C0D" と入力されたとすると、"0D"がc1$に代入されます。
730行 cv=val("&H"+c1$)
16進数の表記の文字列を数値変数に変換(関数val)して、数値変数cvに代入します。

140 '
150 'ファイルオープン、コマンド入力処理
160 '
170 input "File Name :", file$
180 open file$ as #1
190 input "-",cmnd$: c$=left$(cmnd$,1)
200 if c$="Q" or c$="q" then goto 590
210 if c$="C" or c$="c" then gosub 720
220 if c$="D" or c$="d" then goto 270
230 goto 190

(途中省略)

590 close:end

(途中省略)

690 '
700 'バイナリデータ検索コマンド処理ルーチン
710 '
720 c1$=mid$(cmnd$,2,2)
730 cv=val("&H"+c1$)
740 return

(3) ダンプ表示
ダンプ表示部の大きな流れは以下の通りです。
(A) データ読み込み(16データづつ)
(B) バイナリー値表示
  ・アドレス表示
  ・16個のバイナリー値表示(Cコマンドで指定された値は赤色表示)
(C) アスキー部表示
(D) サブコマンド処理

まず、(A) データ読み込み(16データづつ)、(B) バイナリー値表示 のコードについて説明します。

270行 if eof(1) then close:goto130
eof( )関数は、ファイルエンドに到達すると-1(=True)を返しますので、その場合はclose処理をして130行に
飛びます。
ファイルが残っていれば0(=False)を返しますので、280行以下の処理を繰り返します。
ここは、if eof(1)=-1 then close:goto130 と書いても同じです。

290行、300行  16バイトづつ読み込みます 
field #1,16 as a$
get #1,n

310行 print right$("0000"+hex$(address),4)+": ";
左にゼロパッティングしてアドレス表示します。ゼロパッティングの定番のコードの書き方です。

360行 b$(i)=mid$(a$,i,1)
a$から1バイトづつ取り出して、b$に代入します

380行 print right$("0"+hex$(asc(b$(i))),2);" ";
asc(b$(i)) --> b$のデータ(文字)のアスキーコード値(キャラクタコード)を取得し 
hex$( ) --> ascは10進の数値変数として結果を返すので、16進数の文字列に変更します
right$("0" + ......, 2) --> 左にゼロパッティングして表示

240 '
250 'ダンプ表示
260 '
270 if eof(1) then close:goto130 'EOFになるまでダンプ継続
280 color 7
290 field #1,16 as a$ '16データづつ取得 -> a$
300 get #1,n
310 print right$("0000"+hex$(address),4)+": ";
320 address=address+16
330 b$(17)=" "
340 'バイナリー値ダンプ表示
350 for i=1 to 16
360 b$(i)=mid$(a$,i,1)
370 if asc(b$(i))=cv then color 3 '検索データの色処理
380 print right$("0"+hex$(asc(b$(i))),2);" ";
390 color 7
400 next

(C) アスキー部表示、(D) サブコマンド処理 の部分です。
440行 if i=1 and kan2=1 then b$(i)=" ":kan2=0:goto 490
先頭の1文字目のデータ(i=1)が、漢字の2バイト目(kan2=1)の可能性(すなわち、前の行の行末
=16文字目が、漢字の1バイト目の可能性)のあるときの処理です。このデータは、前の行のアスキー
表示部で処理済みなので、ここでは空白" "を表示します。

480行 if ((asc(b$(i))>=&h80) and (asc(b$(i))<=&h9f)) or ((asc(b$(i))>=&hE0) and (asc(b$(i))<=&hFC)) then
gosub 630
漢字の1バイト目の可能性があるときは、630行の「2バイト文字処理サブルーチン」を呼びます

530行目〜570行目は、サブコマンドの処理です。

630行目以降は、2バイト文字処理サブルーチンです。
行末(=16バイト目)の場合は、
650 get #1,n+1 --> 次のレコード(16バイト)のデータ読み込み
660 nextb$=left$(a$,1):nextbb=asc(nextb$) --> 先頭の1バイトをnextb$に切り出し
670 if (nextbb>=&h40) and (nextbb<= &hFC) then kan2=1:b$(17)=nextb$
----> 2バイト文字の2バイト目だったら、行末アスキー表示の処理(b$(17)=nextb$)

410 'アスキー表示部処理
420 t$=""
430 for i=1 to 16
440 if i=1 and kan2=1 then b$(i)=" ":kan2=0:goto 490
450 if kan2=1 then kan2=0:goto 490
460 if asc(b$(i))<32 then b$(i)="." '表示できない文字処理
470 '2バイト文字処理
480 if ((asc(b$(i))>=&h80) and (asc(b$(i))<=&h9f)) or ((asc(b$(i))>=&hE0) and (asc(b$(i))<=&hFC)) then
gosub 630
490 t$=t$+b$(i)
500 next
510 print ": ";t$+b$(17)
520 n=n+1
530 k$=inkey$
540 if k$="1" then frag=1:print" 中断します。再開する時は2を、コマンド入力に戻る時は3を押して下さい"
:goto 530
550 if k$="2" then frag=0
560 if k$="3" then frag=0: goto 190
570 if frag=1 then goto 530
580 goto 270

600 '
610 '2バイト文字処理ルーチン
620 '
630 if i=16 then goto 650
640 kan2=1: goto 680
650 get #1,n+1
660 nextb$=left$(a$,1):nextbb=asc(nextb$)
670 if (nextbb>=&h40) and (nextbb<= &hFC) then kan2=1:b$(17)=nextb$
680 return



TOP PAGE >Basic活用研究目次