comet2monitorの追加と、モニター機能作成
authorj8takagi <j8takagi@nifty.com>
Tue, 10 Jul 2018 14:46:05 +0000 (23:46 +0900)
committerj8takagi <j8takagi@nifty.com>
Tue, 10 Jul 2018 14:46:05 +0000 (23:46 +0900)
19 files changed:
.gitignore
Makefile
doc/manual.texi
doc_inner/Makefile
include/assemble.h
include/disassemble.h
include/exec.h
include/monitor.h
include/struct.h
src/.gitignore
src/Makefile
src/assemble.c
src/casl2.c
src/comet2.c
src/comet2monitor.c
src/disassemble.c
src/exec.c
src/monitor.c
src/struct.c

index a78ba84..f72eba1 100644 (file)
@@ -2,6 +2,7 @@
 /comet2
 /dumpword
 /casl2rev
+/comet2monitor
 *.o
 *.o.casl
 !as/sample/hello.o
index 29e29f1..bff31db 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -34,13 +34,13 @@ VERSIONFILES := include/version.h \
         test/system/comet2_opt/opt_v/0.txt \
         test/system/dumpword/opt_v/0.txt
 
-CMDFILES := casl2 comet2 dumpword casl2rev
+CMDFILES := casl2 comet2 dumpword casl2rev comet2monitor
 
 all: build INSTALL gtags
 
 build:
        $(MAKE) -C src all
-       @(for f in $(CMDFILES); do if test src/$$f -nt $$f; then $(CP) src/$$f $$f; fi; done)
+       @(for f in $(CMDFILES); do if test ! -e $$f -o src/$$f -nt $$f; then $(CP) src/$$f $$f; fi; done)
 
 gtags:
        $(if $(strip $(shell $(WHICH) $(GTAGS))),$(GTAGS),@$(ECHO) '$(GTAGS): not found')
index 1c27aa2..69ff038 100644 (file)
@@ -93,9 +93,8 @@ YACASL2の動作はCASL IIの仕様に準拠しているため、情報処理試
 また、本パッケージ中にCASL IIのサンプルプログラムが多数収録されています。
 
 YACASL2は、「ふつうの処理系」として動作します。
-ほかの多くのCASL IIエミュレータと違い、デバッガとして動作したり、
-コンピュータ内部の模式図を表示したりすることはありません。
-そのかわり、YACASL2は、次のような動作内容をすべてテキストで出力します。
+YACASL2の操作は、端末上のコマンドラインインターフェイス(CLI)で操作します。
+YACASL2は、次のような動作内容をすべてテキストで出力します。
 
 @itemize @bullet
 
@@ -112,10 +111,12 @@ YACASL2は、「ふつうの処理系」として動作します。
 実行時のメモリの内容
 @end itemize
 
-出力された動作内容は、GNU/Linuxのさまざまなコマンド、
+YACASL2では、機械コードモニターを使い、動作中のCPUやメモリーを調べたりデバッグしたりすることもできます。
+
+また、出力された動作内容は、GNU/Linuxのさまざまなコマンド、
 たとえば、@command{cat}、@command{less}、@command{grep}、@command{wc}などを使って解析できます。
 
-YACASL2の操作は、端末上のコマンドラインインターフェイスで行います。
+
 
 @node Sample usage, casl2 invocation, Overview, Top
 @chapter YACASL2の使用例
@@ -821,7 +822,7 @@ $ @kbd{dumpword '#0048'}
  #0048:     72 = #0048 = 0000000001001000 = 'H'
 @end example
 
-@unnumberedsubsec オプション
+@unnumberedsec オプション
 
 @command{dumpword}は、次のオプションを指定できます。
 
index cdea34f..e57591f 100644 (file)
@@ -35,7 +35,7 @@ $(DOXYGEN_DIR): $(DOXYSRCDIR)/Doxyfile ../src ../include
        $(CD) $(DOXYSRCDIR) && $(DOXYGEN)
 
 $(DOXYSRCDIR)/Doxyfile: Doxyfile
-       $(CP) -f Doxyfile $(DOXYSRCDIR)/
+       @$(CP) -vf Doxyfile $(DOXYSRCDIR)/
 
 # htagsのHTMLドキュメント作成先は、
 # 引数DIRで指定されたディレクトリーの下のHTMLディレクトリー
index 468f082..78f5b8a 100644 (file)
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include "cerr.h"
 #include "cmem.h"
+#include "exec.h"
 #include "hash.h"
 #include "struct.h"
 #include "word.h"
@@ -186,6 +187,17 @@ void addcerrlist_assemble();
  */
 bool assemblefile(const char *file, PASS pass);
 
+/**
+ * @brief 指定された1つまたは複数のファイルを2回アセンブル
+ *
+ * @return なし
+ *
+ * @param filec アセンブルするファイルの数
+ * @param filev アセンブルするファイル名の配列
+ * @param adr アセンブル結果を格納するアドレス
+ */
+void assemble(int filec, char *filev[], WORD adr);
+
 /**
  * @brief ファイルにアセンブル結果を書き込む
  *
index 345e727..4a56df6 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef DISASSEMBLE_INCLUDE
 #define DISASSEMBLE_INCLUDE
 
-#include "exec.h"
+#include "struct.h"
 
 /**
  * @brief CASL IIのオブジェクトファイルを逆アセンブルし、標準出力へ出力する
index 432d3fd..7940829 100644 (file)
@@ -23,11 +23,12 @@ typedef struct {
     bool trace;           /**<レジストリの内容をステップごとに表示する場合はtrue */
     bool logical;         /**<レジストリの内容を論理値(0から65535)で表示する場合はtrue */
     bool dump;            /**<メモリの内容をステップごとに表示する場合はtrue */
-    bool step;           /**<ステップ実行の場合はtrue */
+    bool monitor;         /**<モニターモードの場合はtrue */
+    bool step;            /**<ステップ実行の場合はtrue */
 } EXECMODE;
 
 /**
- * @brief 実行モード: trace, logical, dump, step
+ * @brief 実行モード: trace, logical, dump, monitor, step
  */
 extern EXECMODE execmode;
 
@@ -43,17 +44,13 @@ void addcerrlist_load();
 
 /**
  * @brief 指定されたファイルからアセンブル結果を読み込む
- */
-bool loadassemble(const char *file);
-
-/**
- * @brief 汎用レジスタの番号からレジスタを表す文字列を返す
  *
- * @return 汎用レジスタを表す文字列。「GR0」「GR1」・・・「GR7」のいずれか
+ * @return 読み込み終了アドレス。読み込めなかった場合は、0
  *
- * @param word レジスタ番号[0-7]を表すWORD値
+ * @param file 読み込むファイル名
+ * @param start 読み込み開始アドレス
  */
-char *grstr(WORD word);
+WORD loadassemble(const char *file, WORD start);
 
 /**
  * @class Exec
index 9a83f88..b2f648e 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <assert.h>
+#include "assemble.h"
 #include "hash.h"
 #include "cmem.h"
 #include "cerr.h"
index d4d87d2..e36c13f 100644 (file)
@@ -125,6 +125,15 @@ typedef struct {
 
 extern EXECPTR *execptr;
 
+/**
+ * @brief 汎用レジスタの番号からレジスタを表す文字列を返す
+ *
+ * @return 汎用レジスタを表す文字列。「GR0」「GR1」・・・「GR7」のいずれか
+ *
+ * @param word レジスタ番号[0-7]を表すWORD値
+ */
+char *grstr(WORD word);
+
 /**
  * COMET II仮想マシンのリセット
  */
index b9840fb..344654b 100644 (file)
@@ -5,4 +5,5 @@ tags
 casl2
 comet2
 dumpword
-casl2rev
\ No newline at end of file
+casl2rev
+comet2monitor
index 59749cc..fbc5ad5 100644 (file)
@@ -1,9 +1,9 @@
 # ソースファイル。グループに分類
-CMDOBJ := casl2 comet2 dumpword casl2rev
+CMDOBJ := casl2 comet2 dumpword casl2rev comet2monitor
 COMMONOBJ := word cmem cerr
-CASL2OBJ := struct hash
+STRUCTOBJ := struct hash
 ASOBJ := assemble token label
-EXECOBJ := exec dump disassemble monitor
+EXECOBJ := exec dump monitor disassemble
 
 # ヘッダファイル
 INCLUDEDIR := ../include
@@ -21,22 +21,24 @@ WHICH := which
 
 all: build tag
 
-# casl2、comet2、dumpwordのビルド
+# casl2ã\80\81comet2ã\80\81dumpwordã\80\81casl2revã\80\81comet2monitorã\81®ã\83\93ã\83«ã\83\89
 build: $(CMDOBJ)
 
-casl2: $(addsuffix .o,casl2 $(COMMONOBJ) $(CASL2OBJ) $(ASOBJ) $(EXECOBJ))
+casl2: $(addsuffix .o,casl2 $(COMMONOBJ) $(STRUCTOBJ) $(ASOBJ) $(EXECOBJ))
 
-comet2: $(addsuffix .o,comet2 $(COMMONOBJ) $(CASL2OBJ) $(EXECOBJ))
+comet2: $(addsuffix .o,comet2 $(COMMONOBJ) $(STRUCTOBJ) $(ASOBJ) $(EXECOBJ))
 
 dumpword: $(addsuffix .o,dumpword $(COMMONOBJ))
 
-casl2rev:$(addsuffix .o,casl2rev $(COMMONOBJ) $(CASL2OBJ) $(EXECOBJ))
+casl2rev:$(addsuffix .o,casl2rev $(COMMONOBJ) $(STRUCTOBJ) $(ASOBJ) $(EXECOBJ))
+
+comet2monitor:$(addsuffix .o,comet2monitor $(COMMONOBJ) $(STRUCTOBJ) $(ASOBJ) $(EXECOBJ))
 
 # .dファイルからヘッダファイルの依存関係を取得する
 # tags、check、clean、.d で終わるターゲットの場合は除く
 NODEP := %tags %check %clean %.d
 ifeq ($(filter $(NODEP),$(MAKECMDGOALS)),)
-  -include $(addsuffix .d,$(CMDOBJ) $(COMMONOBJ) $(CASL2OBJ) $(ASOBJ) $(EXECOBJ))
+  -include $(addsuffix .d,$(CMDOBJ) $(COMMONOBJ) $(STRUCTOBJ) $(ASOBJ) $(EXECOBJ))
 endif
 
 # tagファイル作成 - ctags & etags
index 8318d18..ecfe900 100644 (file)
@@ -749,6 +749,50 @@ bool assemblefile(const char *file, PASS pass)
     return (cerr->num == 0) ? true : false;
 }
 
+void assemble(int filec, char *filev[], WORD adr)
+{
+    int i;
+    PASS pass;
+    WORD bp[filec];
+
+    create_cmdtype_code();                         /* 命令の名前とタイプがキーのハッシュ表を作成 */
+    asptr = malloc_chk(sizeof(ASPTR), "asptr");    /* アセンブル時のプロパティ用の領域確保 */
+    asptr->prog = malloc_chk(LABELSIZE + 1, "asptr.prog");
+    asptr->ptr = adr;
+    /* アセンブル。ラベル表作成のため、2回行う */
+    for(pass = FIRST; pass <= SECOND; pass++) {
+        for(i = 0; i < filec; i++) {
+            /* データの格納開始位置 */
+            if(pass == FIRST) {
+                bp[i] = asptr->ptr;
+            } else if(pass == SECOND) {
+                asptr->ptr = bp[i];
+            }
+            if(execmode.trace == true || execmode.dump == true ||
+               asmode.src == true || asmode.label == true || asmode.asdetail == true)
+            {
+                fprintf(stdout, "\nAssemble %s (%d)\n", filev[i], pass);
+            }
+            /* ファイルをアセンブル */
+            if(assemblefile(filev[i], pass) == false) {
+                goto asfin;
+            }
+        }
+        if(pass == FIRST && asmode.label == true) {
+            fprintf(stdout, "\nLabel::::\n");
+            printlabel();
+            if(asmode.onlylabel == true) {
+                break;
+            }
+        }
+    }
+asfin:
+    freelabel();                                  /* ラベルハッシュ表を解放 */
+    free_cmdtype_code();                          /* 命令の名前とタイプがキーのハッシュ表を解放 */
+    FREE(asptr->prog);                            /* アセンブル時のプロパティを解放 */
+    FREE(asptr);
+}
+
 /* assemble.hで定義された関数群 */
 void addcerrlist_assemble()
 {
index a54adb8..fb4290a 100644 (file)
@@ -1,6 +1,5 @@
 #include "package.h"
 #include "assemble.h"
-#include "exec.h"
 
 /**
  * @brief CASL IIのエラーをエラーリストに追加
@@ -18,16 +17,6 @@ void addcerrlist_casl2();
  */
 const char *objfile_name(const char *str);
 
-/**
- * @brief 指定された1つまたは複数のファイルを2回アセンブル
- *
- * @return なし
- *
- * @param filec アセンブルするファイルの数
- * @param filev アセンブルするファイル名の配列
- */
-void assemble(int filec, char *filev[]);
-
 /**
  * @brief casl2コマンドのオプション
  */
@@ -69,50 +58,6 @@ const char *objfile_name(const char *str)
     return (str == NULL) ? default_name : str;
 }
 
-void assemble(int filec, char *filev[])
-{
-    int i;
-    PASS pass;
-    WORD bp[filec];
-
-    create_cmdtype_code();                         /* 命令の名前とタイプがキーのハッシュ表を作成 */
-    asptr = malloc_chk(sizeof(ASPTR), "asptr");    /* アセンブル時のプロパティ用の領域確保 */
-    asptr->prog = malloc_chk(LABELSIZE + 1, "asptr.prog");
-    asptr->ptr = 0;
-    /* アセンブル。ラベル表作成のため、2回行う */
-    for(pass = FIRST; pass <= SECOND; pass++) {
-        for(i = 0; i < filec; i++) {
-            /* データの格納開始位置 */
-            if(pass == FIRST) {
-                bp[i] = asptr->ptr;
-            } else if(pass == SECOND) {
-                asptr->ptr = bp[i];
-            }
-            if(execmode.trace == true || execmode.dump == true ||
-               asmode.src == true || asmode.label == true || asmode.asdetail == true)
-            {
-                fprintf(stdout, "\nAssemble %s (%d)\n", filev[i], pass);
-            }
-            /* ファイルをアセンブル */
-            if(assemblefile(filev[i], pass) == false) {
-                goto asfin;
-            }
-        }
-        if(pass == FIRST && asmode.label == true) {
-            fprintf(stdout, "\nLabel::::\n");
-            printlabel();
-            if(asmode.onlylabel == true) {
-                break;
-            }
-        }
-    }
-asfin:
-    freelabel();                                  /* ラベルハッシュ表を解放 */
-    free_cmdtype_code();                          /* 命令の名前とタイプがキーのハッシュ表を解放 */
-    FREE(asptr->prog);                            /* アセンブル時のプロパティを解放 */
-    FREE(asptr);
-}
-
 /**
  * @brief casl2コマンドのメイン
  *
@@ -204,7 +149,7 @@ int main(int argc, char *argv[])
     for(i = 0; i < argc - optind; i++) {           /* 引数からファイル名配列を取得 */
         af[i] = argv[optind + i];
     }
-    assemble(i, af);                               /* アセンブル */
+    assemble(i, af, 0);                            /* アセンブル */
     if(asmode.onlylabel == true || cerr->num > 0) {
         goto casl2fin;
     }
index a3d6ee1..55bab75 100644 (file)
@@ -46,7 +46,7 @@ int main(int argc, char *argv[])
             execmode.dump = true;
             break;
         case 'm':
-            execmode.step = true;
+            execmode.monitor = true;
             break;
         case 'M':
             memsize = atoi(optarg);
@@ -73,18 +73,15 @@ int main(int argc, char *argv[])
     if(argv[optind] == NULL) {
         setcerr(211, "");    /* object file not specified */
         fprintf(stderr, "comet2 error - %d: %s\n", cerr->num, cerr->msg);
-        freecerr();             /* エラーの解放 */
-        exit(1);
+        goto fin;
     }
-
-    /* COMET II仮想マシンのリセット */
-    reset(memsize, clocks);
+    reset(memsize, clocks);     /* COMET II仮想マシンのリセット */
     execptr->start = 0;
-    if(loadassemble(argv[optind]) == true) {
-        exec();                /* プログラム実行 */
+    if((execptr->end = loadassemble(argv[optind], execptr->start)) > 0 && cerr->num == 0) {
+        exec();                 /* プログラム実行 */
     }
-    /* COMET II仮想マシンのシャットダウン */
-    shutdown();
+    shutdown();                 /* COMET II仮想マシンのシャットダウン */
+fin:
     stat = (cerr->num == 0) ? 0 : 1;
     freecerr();                 /* エラーの解放 */
     return stat;
index d6fcbea..65f4241 100644 (file)
@@ -24,7 +24,7 @@ int main(int argc, char *argv[])
 {
     int memsize = DEFAULT_MEMSIZE, clocks = DEFAULT_CLOCKS;
     int opt, stat = 0;
-    const char *version = PACKAGE_VERSION,  *cmdversion = "comet2 of YACASL2 version %s\n";
+    const char *version = PACKAGE_VERSION,  *cmdversion = "comet2monitor: COMET II machine code monitor of YACASL2 version %s\n";
     const char *usage = "Usage: %s [-vh] [-M <MEMORYSIZE>] [-C <CLOCKS>]\n";
 
     /* オプションの処理 */
@@ -55,8 +55,8 @@ int main(int argc, char *argv[])
     /* COMET II仮想マシンのリセット */
     reset(memsize, clocks);
     execptr->start = 0;
-    execmode.step = true;
-    exec();                /* プログラム実行 */
+    execmode.monitor = true;
+    exec();                     /* プログラム実行 */
     shutdown();
     stat = (cerr->num == 0) ? 0 : 1;
     freecerr();                 /* エラーの解放 */
index ff24e3c..8f3c9d7 100644 (file)
@@ -74,10 +74,7 @@ void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pra
  *
  * @return なし
  *
- * @param cmdtype コマンドの種類
- * @param *cmdname コマンドの名前
  * @param word ワード値
- * @param adr アドレス値
  * @param pradr 次に実行すべき命令語の先頭アドレス
  */
 void disassemble_dc(WORD word, WORD pradr);
index b22fbf4..c7c125e 100644 (file)
@@ -94,9 +94,9 @@ static CERR cerr_load[] = {
 };
 
 /**
- * @brief 実行モード: trace, logical, dump, step
+ * @brief 実行モード: trace, logical, dump, monitor, step
  */
-EXECMODE execmode = {false, false, false, false};
+EXECMODE execmode = {false, false, false, false, false};
 
 char *pr2str(WORD pr)
 {
@@ -226,25 +226,23 @@ void addcerrlist_exec()
     addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec);
 }
 
-bool loadassemble(const char *file)
+WORD loadassemble(const char *file, WORD start)
 {
     FILE *fp;
-    bool stat = true;
+    WORD end;
 
     assert(file != NULL);
     if((fp = fopen(file, "rb")) == NULL) {
         perror(file);
-        return false;
+        return 0;
     }
-    execptr->end = execptr->start +
-        fread(sys->memory, sizeof(WORD), sys->memsize - execptr->start, fp);
-    if(execptr->end == sys->memsize) {
+    end = start + fread(sys->memory + start, sizeof(WORD), sys->memsize - start, fp);
+    if(end == sys->memsize) {
         setcerr(210, file);    /* load - memory overflow */
         fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg);
-        stat = false;
     }
     fclose(fp);
-    return stat;
+    return end;
 }
 
 void nop()
@@ -763,19 +761,12 @@ void svc()
     sys->cpu->pr += 2;
 }
 
-char *grstr(WORD word)
-{
-    assert(word <= 7);
-    char *str = malloc_chk(3 + 1, "grstr.str");
-    sprintf(str, "GR%d", word);
-    return str;
-}
-
 void exec()
 {
     clock_t clock_begin, clock_end;
     void (*cmdptr)();
     char *s;
+    const char *monmsg = "COMET II machine code monitor. Type ? for help.\n";
 
     create_code_cmdtype();                          /* 命令のコードとタイプがキーのハッシュ表を作成 */
     if(execmode.trace == true) {
@@ -795,8 +786,14 @@ void exec()
             }
             fprintf(stdout, "\n");
         }
-        /* デバッガーモードの場合、デバッガーを起動 */
-        if(execmode.step == true || getbps(sys->cpu->pr) == true) {
+        /* ステップモードまたはブレークポイントの場合、モニターを起動 */
+        if(
+            (execmode.monitor == true && sys->cpu->pr == execptr->start) ||
+            execmode.step == true || getbps(sys->cpu->pr) == true)
+        {
+            if(sys->cpu->pr == execptr->start) {
+                fprintf(stdout, "%s", monmsg);
+            }
             monitor();
         }
         /* プログラムレジスタをチェック */
@@ -824,9 +821,14 @@ void exec()
         if(cerr->num > 0) {
             goto execfin;
         }
-        /* 終了フラグがtrueの場合は、正常終了 */
+        /* 終了フラグがtrueの場合は、モニターまたは正常終了 */
         if(execptr->stop == true) {
-            break;
+            if(execmode.monitor == true) {
+                fprintf(stdout, "Return to top.\n");
+                monitor();
+            } else {
+                break;
+            }
         }
         /* クロック周波数の設定 */
         do {
index 24f2156..4278c6a 100644 (file)
@@ -253,13 +253,26 @@ void mon_dump(int argc, char *argv[])
 MONCMDTYPE monitorcmd(char *cmd, MONARGS *args)
 {
     MONCMDTYPE cmdtype = MONREPEAT;
-    if(stracmp(cmd, 2, (char* []){"b", "break"})) {
+    if(stracmp(cmd, 2, (char* []){"a", "assemble"})) {
+        if(args->argc == 0) {
+            fprintf(stderr, "Error: Input file name.\n");
+        } else if(args->argc == 1) {
+            assemble(1, (char* []){args->argv[0]}, 0);
+        } else {
+            assemble(1, (char* []){args->argv[0]}, nh2word(args->argv[1]));
+        }
+    } else if(stracmp(cmd, 2, (char* []){"b", "break"})) {
         mon_break(args->argc, args->argv);
     } else if(stracmp(cmd, 2, (char* []){"c", "continue"})) {
         execmode.step = false;
         cmdtype = MONNEXT;
     } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) {
         mon_dump(args->argc, args->argv);
+    } else if(stracmp(cmd, 2, (char* []){"l", "load"})) {
+        loadassemble(args->argv[0], nh2word(args->argv[1]));
+    } else if(stracmp(cmd, 2, (char* []){"n", "next"})) {
+        execmode.step = true;
+        cmdtype = MONNEXT;
     } else if(stracmp(cmd, 2, (char* []){"q", "quit"})) {
         fprintf(stdout, "Quit: COMET II monitor\n");
         cmdtype = MONQUIT;
@@ -267,9 +280,9 @@ MONCMDTYPE monitorcmd(char *cmd, MONARGS *args)
         if(args->argc == 2) {
             disassemble_memory(nh2word(args->argv[0]), nh2word(args->argv[1]));
         }
-    } else if(stracmp(cmd, 2, (char* []){"s", "step"})) {
-        execmode.step = true;
-        cmdtype = MONNEXT;
+    } else if(stracmp(cmd, 1, (char* []){"reset"})) {
+        fprintf(stdout, "Reset COMET II.\n");
+        reset(sys->memsize, sys->clocks);     /* COMET II仮想マシンのリセット */
     } else if(stracmp(cmd, 2, (char* []){"t", "trace"})) {
         if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) {
             execmode.logical = false;
@@ -294,9 +307,12 @@ MONCMDTYPE monitorcmd(char *cmd, MONARGS *args)
         fprintf(stdout, "b[reak] -- Manipulate Breakpoints. See details, `b ?'.\n");
         fprintf(stdout, "c[ontinue] -- Continue running your program.\n");
         fprintf(stdout, "d[ump] -- Display memory dump. `d[ump] a[uto]/n[oauto]' set auto/noauto display.\n");
+        fprintf(stdout, "l[oad] -- Load object from a file to the memory. `l[oad] <filepath> <address>' if address is omitted, load to address 0.\n");
+        fprintf(stdout, "n[ext] -- Go next instruction.\n");
         fprintf(stdout, "q[uit] -- Quit running your program.\n");
+        fprintf(stdout, "reset -- Reset the system.\n");
         fprintf(stdout, "r[everse] -- Disassemble memory. `r[everse] <start address> <end address>.\n");
-        fprintf(stdout, "s[tep] -- Step by step running your program until next interaction.\n");
+        fprintf(stdout, "s[ave] -- Save object from the memory to a file. `s[ave] <filepath> [<start address1> [<end address>]]' if <start address> and <end address> is omitted, save the whole memory. if <end address> is omitted, save the memory after <start address>.\n");
         fprintf(stdout, "t[race] -- Display CPU register. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
         fprintf(stdout, "T[race] -- Display CPU register as logical value. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n");
         fprintf(stdout, "?/h[elp] -- Display this help.\n");
@@ -327,8 +343,9 @@ void monitor()
     char *buf, *p;
     MONCMDLINE *moncmdl;
     MONCMDTYPE cmdtype = MONREPEAT;
+
     do {
-        fprintf(stdout, "COMET II (Type ? for help) > ");
+        fprintf(stdout, "- ");
         buf = malloc_chk(MONINSIZE + 1, "monitor.buf");
         fgets(buf, MONINSIZE, stdin);
         if((p = strchr(buf, '\n')) != NULL) {
index c1a1542..12caf87 100644 (file)
@@ -238,6 +238,18 @@ char *getcmdname(WORD code)
     return cmd;
 }
 
+/**
+ * 汎用レジスタの番号からレジスタを表す文字列を返す
+ */
+
+char *grstr(WORD word)
+{
+    assert(word <= 7);
+    char *str = malloc_chk(3 + 1, "grstr.str");
+    sprintf(str, "GR%d", word);
+    return str;
+}
+
 /**
  * コードがキーの命令ハッシュ表を解放する
  */