From: j8takagi Date: Thu, 5 Jul 2018 07:02:44 +0000 (+0900) Subject: 逆アセンブル出力と、マシンコードモニター機能の修正 X-Git-Tag: v0.5p1~9 X-Git-Url: https://j8takagi.net/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=15a07be760d84746bbace2d70326cd939f4568fd;p=YACASL2.git 逆アセンブル出力と、マシンコードモニター機能の修正 --- diff --git a/include/cmem.h b/include/cmem.h index c5bb6e8..132ef28 100644 --- a/include/cmem.h +++ b/include/cmem.h @@ -31,7 +31,7 @@ * @param size メモリーのサイズ * @param tag エラーメッセージなどで表示されるタグ */ -void *malloc_chk(size_t size, char *tag); +void *malloc_chk(size_t size, const char *tag); /** * @brief 領域の数とサイズを指定してメモリーを確保するcallocを実行する diff --git a/include/disassemble.h b/include/disassemble.h new file mode 100644 index 0000000..345e727 --- /dev/null +++ b/include/disassemble.h @@ -0,0 +1,25 @@ +#ifndef DISASSEMBLE_INCLUDE +#define DISASSEMBLE_INCLUDE + +#include "exec.h" + +/** + * @brief CASL IIのオブジェクトファイルを逆アセンブルし、標準出力へ出力する + * + * @return 正常終了時は0、異常終了時は0以外 + * + * @param *file オブジェクトファイルのファイル名 + */ +bool disassemble_file(const char *file); + +/** + * @brief COMET IIのメモリーを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param *start 逆アセンブルの開始位置 + * @param *end 逆アセンブルの終了位置 + */ +void disassemble_memory(WORD start, WORD end); + +#endif /* end of DISASSEMBLE_INCLUDE */ diff --git a/include/exec.h b/include/exec.h index 3e36e4b..432d3fd 100644 --- a/include/exec.h +++ b/include/exec.h @@ -10,6 +10,7 @@ #include "cmem.h" #include "cerr.h" #include "monitor.h" +#include "disassemble.h" enum { INSIZE = 256 /**start = 0; + execmode.step = true; + exec(); /* プログラム実行 */ + shutdown(); + stat = (cerr->num == 0) ? 0 : 1; + freecerr(); /* エラーの解放 */ + return stat; +} diff --git a/src/disassemble.c b/src/disassemble.c new file mode 100644 index 0000000..f2df812 --- /dev/null +++ b/src/disassemble.c @@ -0,0 +1,218 @@ +#include "disassemble.h" + +/** + * @brief 機械コードの出力列 + */ +int codecol = 38; + +/** + * @brief 機械コードをコメントとして標準出力へ出力する + * + * @return なし + * + * @param ascol アセンブラの列位置 + * @param pradr 次に実行すべき命令語の先頭アドレス + * @param wordc ワード値の数 + * @param wordv ワード値の配列 + */ +void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]); + +/** + * @brief 種類がR_ADRまたはR_ADR_Xのコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param cmdtype コマンドの種類 + * @param *cmdname コマンドの名前 + * @param word ワード値 + * @param adr アドレス値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr); + +/** + * @brief 種類がR1_R2またはR_のコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param cmdtype コマンドの種類 + * @param *cmdname コマンドの名前 + * @param word ワード値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr); + +/** + * @brief DCコマンドを逆アセンブルし、標準出力へ出力する + * + * @return なし + * + * @param cmdtype コマンドの種類 + * @param *cmdname コマンドの名前 + * @param word ワード値 + * @param adr アドレス値 + * @param pradr 次に実行すべき命令語の先頭アドレス + */ +void disassemble_dc(WORD word, WORD pradr); + +void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[]) +{ + int i; + for(i = 0; i < codecol-ascol; i++){ + fprintf(stdout, " "); + } + if(wordc == 1) { + fprintf(stdout, "; #%04X: #%04X", pradr, wordv[0]); + } else if(wordc == 2) { + fprintf(stdout, "; #%04X: #%04X #%04X", pradr, wordv[0], wordv[1]); + } +} +void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD pradr) +{ + WORD x; + char *g; + int cnt = 0; + cnt += fprintf(stdout, " %-7s ", cmdname); + if(cmdtype == R_ADR_X) { + cnt += fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4)); + FREE(g); + } + cnt += fprintf(stdout, "#%04X", adr); + if((x = (word & 0x000F)) != 0) { + cnt += fprintf(stdout, ",%s", g = grstr(x)); + FREE(g); + } + disassemble_puts_code(cnt, pradr, 2, (WORD []){word, adr}); +} + +void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD pradr) +{ + char *g, *g1, *g2; + int cnt = 0; + cnt += fprintf(stdout, " %-7s ", cmdname); + if(cmdtype == R1_R2) { + g1 = grstr((word & 0x00F0) >> 4); + g2 = grstr(word & 0x000F); + cnt += fprintf(stdout, "%s,%s", g1, g2); + FREE(g1); + FREE(g2); + } else if(cmdtype == R_) { + g = grstr((word & 0x00F0) >> 4); + cnt += fprintf(stdout, "%s", g); + FREE(g); + } + disassemble_puts_code(cnt, pradr, 1, (WORD []){word}); +} + +void disassemble_dc(WORD word, WORD pradr) +{ + int cnt = 0; + cnt = fprintf(stdout, " DC %-5d ", word); + disassemble_puts_code(cnt, pradr, 1, (WORD []){word}); + fprintf(stdout, " ::" ); + print_dumpword(word, true); +} + +void disassemble_ds(WORD wcnt, WORD pradr) +{ + int cnt = 0, i; + cnt = fprintf(stdout, " DS %-5d ", wcnt); + disassemble_puts_code(cnt, pradr, 1, (WORD []){0}); + for(i = 0; i < wcnt - 1; i++) { + fprintf(stdout, "\n"); + disassemble_puts_code(0, pradr+1, 1, (WORD []){0}); + } +} + +bool disassemble_file(const char *file) +{ + bool stat = true; + FILE *fp; + WORD i = 0, w, cmd, adr, dsarea; + CMDTYPE cmdtype = 0; + char *cmdname; + bool inst = true; + + assert(file != NULL); + if((fp = fopen(file, "rb")) == NULL) { + perror(file); + return false; + } + + create_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を作成 */ + + fprintf(stdout, "MAIN START\n"); + for(fread(&w, sizeof(WORD), 1, fp); !feof(fp); i++, fread(&w, sizeof(WORD), 1, fp)) { + cmd = w & 0xFF00; + cmdname = getcmdname(cmd); + cmdtype = getcmdtype(cmd); + if(w == 0){ + if(inst == true) { + disassemble_cmd_r(NONE, "nop", 0, i); + } else { + dsarea = 1; + do { + fread(&w, sizeof(WORD), 1, fp); + dsarea++; + } while(w == 0 && !feof(fp)); + if(!feof(fp)) { + fseek(fp, -1 * sizeof(WORD) , SEEK_CUR); + } + if(dsarea == 1) { + disassemble_dc(0, i); + } else { + disassemble_ds(dsarea, i); + i += dsarea - 1; + } + } + } else if(cmd == 0) { + disassemble_dc(w, i); + } else { + if(cmdtype == R_ADR_X || cmdtype == ADR_X) { + fread(&adr, sizeof(WORD), 1, fp); + disassemble_cmd_adr_x(cmdtype, cmdname, w, adr, i++); + } else { + disassemble_cmd_r(cmdtype, cmdname, w, i); + } + inst = (cmd != 0x8100) ? true : false; + } + fprintf(stdout, "\n"); + } + fprintf(stdout, " END\n"); + free_code_cmdtype(); + fclose(fp); + return stat; +} + +void disassemble_memory(WORD start, WORD end) +{ + WORD i, w, cmd, adr; + CMDTYPE cmdtype = 0; + char *cmdname; + bool inst = true; + + for(i = start; i <= end; i++) { + w = sys->memory[i]; + cmd = w & 0xFF00; + cmdname = getcmdname(cmd); + cmdtype = getcmdtype(cmd); + if(w == 0) { + if(inst == true) { + disassemble_cmd_r(NONE, "nop", 0, i); + } else { + disassemble_dc(0, i); + } + } else if(cmd == 0) { + disassemble_dc(w, i); + } else { + if(cmdtype == R_ADR_X || cmdtype == ADR_X) { + adr = sys->memory[i+1]; + disassemble_cmd_adr_x(cmdtype, cmdname, w, adr, i++); + } else { + disassemble_cmd_r(cmdtype, cmdname, w, i); + } + inst = (cmd != 0x8100) ? true : false; + } + fprintf(stdout, "\n"); + } +} diff --git a/src/exec.c b/src/exec.c index 2bca011..b22fbf4 100644 --- a/src/exec.c +++ b/src/exec.c @@ -70,16 +70,6 @@ WORD get_adr_x(WORD adr, WORD oprx); */ WORD get_val_adr_x(WORD adr, WORD oprx); -/** - * @brief 汎用レジスタの番号からレジスタを表す文字列を返す - * - * @return 汎用レジスタを表す文字列。「GR0」「GR1」・・・「GR7」のいずれか - * - * @param word レジスタ番号[0-7]を表すWORD値 - */ -char *grstr(WORD word); - - /** * @brief 実行エラーの定義 */ @@ -850,101 +840,3 @@ execfin: fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg); } } - -void disassemble_cmd_adr_x(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD adr, WORD loc) -{ - WORD x; - char *g; - fprintf(stdout, "\t%s\t", cmdname); - if(cmdtype == R_ADR_X) { - fprintf(stdout, "%s,", g = grstr((word & 0x00F0) >> 4)); - FREE(g); - } - fprintf(stdout, "#%04X", adr); - if((x = (word & 0x000F)) != 0) { - fprintf(stdout, ",%s", g = grstr(x)); - FREE(g); - } - fprintf(stdout, "\t\t\t\t; #%04X: #%04X #%04X", loc, word, adr); -} - -void disassemble_cmd_r(CMDTYPE cmdtype, const char *cmdname, WORD word, WORD loc) -{ - char *g, *g1, *g2; - fprintf(stdout, "\t%s", cmdname); - if(cmdtype == R1_R2) { - g1 = grstr((word & 0x00F0) >> 4); - g2 = grstr(word & 0x000F); - fprintf(stdout, "\t%s,%s", g1, g2); - FREE(g1); - FREE(g2); - } else if(cmdtype == R_) { - g = grstr((word & 0x00F0) >> 4); - fprintf(stdout, "\t%s", g); - FREE(g); - } - fprintf(stdout, "\t\t\t\t; #%04X: #%04X", loc, word); -} - -bool disassemble_file(const char *file) -{ - bool stat = true; - FILE *fp; - WORD i = 0, w, cmd, adr; - CMDTYPE cmdtype = 0; - char *cmdname; - - assert(file != NULL); - if((fp = fopen(file, "rb")) == NULL) { - perror(file); - return false; - } - - create_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を作成 */ - - fprintf(stdout, "MAIN\tSTART\n"); - for(fread(&w, sizeof(WORD), 1, fp); !feof(fp); fread(&w, sizeof(WORD), 1, fp)) { - cmd = w & 0xFF00; - cmdname = getcmdname(cmd); - cmdtype = getcmdtype(cmd); - if(cmd == 0xFF00 || (w != 0 && cmd == 0)) { - fprintf(stdout, "\tDC\t%d\t\t\t\t; #%04X: #%04X :: ", w, i++, w); - print_dumpword(w, true); - } else if(cmdtype == R_ADR_X || cmdtype == ADR_X) { - fread(&adr, sizeof(WORD), 1, fp); - disassemble_cmd_adr_x(cmdtype, cmdname, w, adr, i); - i += 2; - } else { - disassemble_cmd_r(cmdtype, cmdname, w, i++); - } - fprintf(stdout, "\n"); - } - fprintf(stdout, "\tEND\n"); - free_code_cmdtype(); - fclose(fp); - return stat; -} - -void disassemble_memory(WORD start, WORD end) -{ - WORD i, w, cmd, adr; - CMDTYPE cmdtype = 0; - char *cmdname; - - for(i = start; i <= end; i++) { - w = sys->memory[i]; - cmd = w & 0xFF00; - cmdname = getcmdname(cmd); - cmdtype = getcmdtype(cmd); - if(cmd == 0xFF00 || (w != 0 && cmd == 0)) { - fprintf(stdout, "\tDC\t%d\t\t\t\t; #%04X: #%04X :: ", w, i, w); - print_dumpword(w, true); - } else if(cmdtype == R_ADR_X || cmdtype == ADR_X) { - adr = sys->memory[i+1]; - disassemble_cmd_adr_x(cmdtype, cmdname, w, adr, i++); - } else { - disassemble_cmd_r(cmdtype, cmdname, w, i); - } - fprintf(stdout, "\n"); - } -} diff --git a/src/monitor.c b/src/monitor.c index d4189fa..24f2156 100644 --- a/src/monitor.c +++ b/src/monitor.c @@ -222,17 +222,54 @@ void mon_break(int argc, char *argv[]) } } +void mon_dump(int argc, char *argv[]) +{ + int i = 0; + WORD start = 0, end = 0xFFFF; + if(argc > 0 && stracmp(argv[0], 2, (char* []){"a", "auto"})) { + execmode.dump = true; + } else if(argc > 0 && stracmp(argv[0], 2, (char* []){"no", "noauto"})) { + execmode.dump = false; + } else { + if(argc > 0) { + start = nh2word(argv[0]); + if(argc > 1) { + end = nh2word(argv[1]); + } + } + dumpmemory(start, end); + if(argc > 2) { + for(i = 2; i < argc; i++) { + if(i > 2) { + fprintf(stderr, " "); + } + fprintf(stderr, "%s", argv[i+1]); + } + fprintf(stderr, ": ignored.\n"); + } + } +} + MONCMDTYPE monitorcmd(char *cmd, MONARGS *args) { MONCMDTYPE cmdtype = MONREPEAT; - if(stracmp(cmd, 2, (char* []){"s", "step"})) { - execmode.step = true; - cmdtype = MONNEXT; - } else if(stracmp(cmd, 2, (char* []){"b", "break"})) { + 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* []){"q", "quit"})) { + fprintf(stdout, "Quit: COMET II monitor\n"); + cmdtype = MONQUIT; + } else if(stracmp(cmd, 2, (char* []){"r", "reverse"})) { + 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, 2, (char* []){"t", "trace"})) { if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) { execmode.logical = false; @@ -253,29 +290,15 @@ MONCMDTYPE monitorcmd(char *cmd, MONARGS *args) fprintf(stdout, "#%04X: Register::::\n", sys->cpu->pr); dspregister(); } - } else if(stracmp(cmd, 2, (char* []){"d", "dump"})) { - if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"a", "auto"})) { - execmode.dump = true; - } else if(args->argc > 0 && stracmp(args->argv[0], 2, (char* []){"no", "noauto"})) { - execmode.dump = false; - } else if(args->argc == 1) { - dumpmemory(nh2word(args->argv[0]), 0xFFFF); - } else if(args->argc > 1) { - dumpmemory(nh2word(args->argv[0]), nh2word(args->argv[1])); - } - } else if(stracmp(cmd, 2, (char* []){"r", "reverse"})) { - if(args->argc == 2) { - disassemble_memory(nh2word(args->argv[0]), nh2word(args->argv[1])); - } - } else if(stracmp(cmd, 2, (char* []){"q", "quit"})) { - fprintf(stdout, "Quit: COMET II monitor\n"); - cmdtype = MONQUIT; } else if(stracmp(cmd, 3, (char* []){"?", "h", "help"})) { - fprintf(stdout, "b[reak] -- Manipulate Breakpoints. Details in `b ?'.\n"); - fprintf(stdout, "s[tep] -- Step by step running your program until next interaction.\n"); + fprintf(stdout, "b[reak] -- Manipulate Breakpoints. See details, `b ?'.\n"); fprintf(stdout, "c[ontinue] -- Continue running your program.\n"); - fprintf(stdout, "t[race] -- Display CPU register. `t[race] a[uto]/n[oauto]' set auto/noauto display. \n"); fprintf(stdout, "d[ump] -- Display memory dump. `d[ump] a[uto]/n[oauto]' set auto/noauto display.\n"); + fprintf(stdout, "q[uit] -- Quit running your program.\n"); + fprintf(stdout, "r[everse] -- Disassemble memory. `r[everse] .\n"); + fprintf(stdout, "s[tep] -- Step by step running your program until next interaction.\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"); } return cmdtype; diff --git a/src/struct.c b/src/struct.c index 0f0ae43..c1a1542 100644 --- a/src/struct.c +++ b/src/struct.c @@ -210,7 +210,7 @@ const void (*getcmdptr(WORD code)) CMDTYPE getcmdtype(WORD code) { CMDTAB *t; - CMDTYPE type = 0; + CMDTYPE type = NONE; for(t = code_cmdtype[hash_code(code)]; t != NULL; t = t->next) { if(code == t->cmd->code) { diff --git a/test/system/casl2rev/sum_10/0.txt b/test/system/casl2rev/sum_10/0.txt index 69e0fc0..af34c97 100644 --- a/test/system/casl2rev/sum_10/0.txt +++ b/test/system/casl2rev/sum_10/0.txt @@ -15,5 +15,5 @@ MAIN START DC 1 ; #0015: #0001 :: 1 = #0001 = 0000000000000001 DC 10 ; #0016: #000A :: 10 = #000A = 0000000000001010 = '\n' DC 1 ; #0017: #0001 :: 1 = #0001 = 0000000000000001 - NOP ; #0018: #0000 + DC 0 ; #0018: #0000 :: 0 = #0000 = 0000000000000000 END