-
Manual Debugger
デバッガリファレンスマニュアル
HI-TECH CはCプログラムに特化したインタラクティブツールが提供されています。これは"ソースレベル"のデバッガではありません。つまり、Cソースコードの知識はありますが、Cシンボルを扱う仕組みがあり、Cの関数を呼び出しシーケンスも表示できます。
コマンド構造はadbとして知られるUnixデバッガをモデルにしています。これはメモリを基数で?表示したり、ブレイクポイントを設定、削除したりできます。これは これらに関連したコマンドを 繰り返しを計上したり、できます。
DEBUGの起動
デバッガはDEBUGコマンドで起動します。0-2個のファイル引数をとります。最初の引数はデバッグされる.COMフォーマットのファイル名で二番目はシンボルファイル名です。シンボルファイル名が省略された場合、シンボルは使用できません。.COMファイルが省略された場合、コードが読み込まれません。いかに例を挙げます。
DEBUG fred.com DEBUG bill.com l.sym
1.2. 実行時の構築??
DEBUGは普通の場合、 デバッグされるものがTPAの最初から読み込めるよう実行時にBDOSの前に自分自身を再配置します。5番目のBDOSエントリはBDOSのベース部分ではなく、むしろシンボルテーブルを反映して変更されます。そのため、シンボルテーブルとデバッガは、デバッガされるもののスタックによって上書きされることはありません。
デバッガはどんな.COMファイルでも使えます。しかし、シンボリック機構?でのアドバンテージを得るために、通常、Cコマンドの-Fオプションとともに使用するシンボルファイルの生成が必要です。このがいるはシンボルが一行ごとに 構成されています。
ブレークポイントはRST 8 命令のコードとして挿入されます。デバッガのトラップハンドラのために、ジャンプはロケーション8に置かれます。システムがRST 8を割り込みに使っているとしたら不幸なことですが、他の場所をリスタートの場所に使う、という以上のことではないでしょう。
コマンド
デバッガの基本的なコマンド様式は以下の通りです。
address , count command modifier extrastuff
これはちょっとあいまいに見えるかもしれませんが、見ておいてください。addressとcountはエクスプレッション(式)で、単純な16進数です。addressとcountはオプション的で、addressがなくcountだけが指定された時、カンマは必須です。 commandは何をすべきかを命令する一文字です。モディファイアはさらにどんなコマンドか決定する他の文字です??extrastuffはある種の命令に依存しますが、通常は省略されます。
エクスプレッション(式)
式は次のものから構成されます。
- .
- この値は現在の位置(カレントPC?もしくは最後のブレークポイントでは必要ありません。これは内部的な現在地です。)
- SYMBOL
- シンボルテーブルで参照されるシンボルの値です。シンボルが見つからない場合は、アンダースコアと同じシンボルが前につきます??。これはコンパイラが、アンダースコアが付いていないCシンボルを参照することを可能にします??。
- INTEGER
- 16進数の整数です。数値で始まらなくてはいけません。そうでない場合、デバッガはシンボルだと考えます。
- <REGNAME
- これはZ80レジスタに指定された内容を渡します。レジスタ名は通常のZ80の名前で、小文字のみです。下記の$rコマンドも参照してください。
- (EXPR)
- 評価の順番を強制するため、エクスプレッションをカッコでとじることができます。アドレスEXPRの単語の内容です。これはCの間接演算子と似ています??EXPRの逆です。
- *EXPR
- アドレスEXPRのワードの内容です。これはCの非直接的な命令に似ています??
- -EXPR
- EXPRの否定です
- ~EXPR
- EXPRのビット指定です。
- E1+E2
- E1とE2の合計です。
- E1-E2
- E2の値で引いたE1の値です。
- E1*E2
- E2にE2をかけた値です。
- E1%E2
- E1をE2で割った値です。
- E1&E2
- E1をE2でand(論理積)した値です。
カッコは評価の順序を変えられます。
コマンド文字
主要なコマンド文字は/です。これはさまざまな基数や命令のメモリ内容を表示します?正確なフォーマットはモディファイア文字、モディファイア文字が省略された場合は、以前のフォーマットによって決定されます。 モディファイアは以下の通りです。
- i
- Z80命令として表示します。
- h もしくは b
- 16進数のバイトとして表示します。
- o
- 8進数のバイトとして表示します。
- d
- 10進数のバイトとして表示します。
- H もしくは W
- 16進数のワードとして表示します。
- O
- 8進数のワードとして表示します。
- D
- 10進数のワードとして表示します。
- c
- アスキー文字として表示します。
- C
- アスキー文字として表示可能であれば表示しますが、もしそうでない場合は@xのように表示します。xは対応するアルファベット文字になります。
- s
- nullになるまで文字列を表示します。
- a
- シンボル値としてアドレスを表示します。
アドレスが指定された場合、表示は指定されたアドレスから開始します。バイト数、命令、ワード、文字列、もしくはその他が表示されるか、カウントが省略された場合、1が表示されます?以下は例です。
fred,10/b 123/i
最初のコマンドはシンボルfredから16バイトを表示します。二番目は124Hからの一つの命令を表示します。
このようなコマンドが発行されると、dotの値は、表示されているバイトの合計数だけ、一時的に増加します。 RETURN,LINE,FEEDで構成される、その後のコマンドが一時的なdotの増加を恒常的なものにし、/コマンドを実行します。
/コマンドはメモリの変更にも使用できます。/w EXPRはexprの値を現在位置(dot)のメモリに書き込みます。 ワードでもバイトでも、/コマンドで最後に使用されたフォーマットに応じて書き込むことができます。 /wコマンドはバイト、ワード型以外のフォーマットでは発行することができません。そのため、iフォーマットではメモリに書き込めません。ある日ふとインラインアセンブラが組み込まれるかもしれませんが、それはまだです。
]コマンドは/コマンドのようなものですが、メモリよりもむしろI/Oポートを表示するという点が違います。 これはh,b,o,dのフォーマットでのみ使用されます。さらに]wはI/Oポートに書きこむために使用できます。
$コマンドは以下に挙げるいろいろなモディファイアを使用できます。
- c
- Cスタックのバックトレースを表示します。これは最適化されたプログラムでは、信頼できません。なぜなら、オプティマイザーがスタックマニピュレーションコードを変更してしまうからです。これは、実際の引数よりも少ない時に現れます??長い引数は常に2つの整数として現れます。
- b
- 現在設定されたブレークポイントを表示します。
- s
- 与えられたアドレスにマッチするシンボルの限界をセットします??これはsym+offsetとして、値が表示されたときに?オフセットの最大値を決定します。
- w
- ターミナルの幅をアドレスに設定します。初期値は10進数の80です。
- r
- 全てのZ80レジスタの内容を表示します。
:コマンドは以下のモディファイアを持ちます。
アドレスからプログラムを実行します。アドレスが省略された場合は、シンボルをスタートさせようとします??
もし、見つからない場合は、デバッガがエラーを出します(文句をいう?)。
- r
- このコマンドとともにextrastuffがプログラムに対する追加の引数文字列として追加可能です。80H内のデフォルトバッファに入ります?rとextrastuffの間にはスペースが入ることを確認してください。
例
100:r arg1 arg2
- c
- アドレスか、アドレスが省略された場合にはPCのコンテンツから、プログラムを継続します。ブレークポイントの後に使われます。
- s
- cと同様ですが、命令しかカウントしないか、カウントが省略された場合に1を計上します??これらの1ステップはデバック対象です。
- bはアドレスでブレークポイントを設定します。カウントが提供された場合、ブレークポイントはカウント時間になるまで?止まりません。Extrastuffはブレークポイントに当たる度に毎回実行されるコマンドになります??
- b
- コマンドがdotをゼロにした場合、カウントがゼロでなくても、ブレークポイントは止まります。
- .
- アドレスと続く実行に対して、一時的なブレークポイントを設定します。次のブレークポイントに遭遇したときに、この一時的なブレークポイントは削除されます。
- d
- アドレスでブレークポイントを削除します。>コマンドでレジスタの値を変更できます。ワード、バイトレジスタが指定できます。割り込みフラグも変更できます。0はオフを、1はオンを意味します。
例
以下はデバッガ使用の例です。
A>type tst.c main() { int i, j; scanf("%d", &i); printf("%d\n", j); Note the error - j should be i } A>c -f tst.c Compile requesting a symbol file A>debug tst.com l.sym Default symbol file name is l.sym ZDEBUG : printf/i Disassemble at printf _printf: call csv : Step down with RETURN _printf+3: push ix : :b Set a breakpoint here : :r Run the program - no arguments 123 Scanf waits for input - enter 123 Breakpoint _printf+3 _printf+3: push ix Stopped at the breakpoint : $c Get a stack trace _printf(1872,0) 1872 is the format string "d\n" _main() : main/i Look at main() now _main: call csv : Step down with RETURN _main+3: ld hl,FFFC : _main+6: add hl,sp : ,10 Disassemble 16 instructions _main+7: ld sp,hl _main+8: push ix _main+A: pop hl _main+B: dec hl _main+C: dec hl _main+D: push hl _main+E: ld hl,186F _main+11: push hl _main+12: call _scanf _main+15: ld hl,4 _main+18: add hl,sp _main+19: ld sp,hl _main+1A: ld l,(ix+-4) here j is loaded _main+1D: ld h,(ix+-3) _main+20: push hl And pushed onto the stack _main+21: ld hl,1872 : main+1a/i _main+1A: ld l,(ix+-4) : /h Look at the bytes as hex _main+1A: DD Indexing prefix byte : Step down with RETURN _main+1B: 6E : _main+1C: FC The index offset = -4 : /w 0fe Change to -2 : _main+1D: DD : _main+1E: 66 : _main+1F: FD : /w 0ff Change the hi byte to -1 to address i instead of j : :r Run it again 123 Enter the same number again Breakpoint _printf+3 _printf+3: push ix : $c _printf(1872,7B) _main() : 7b=d 7b was the argument above 123 Now we have the correct value : :c Continue the program 123 Which prints the correct value A>