-#include <stdio.h>
-#include <stdlib.h>
-#define _GNU_SOURCE
-#include <getopt.h>
-#include <assert.h>
-
-#include "exec.h"
-#include "cmem.h"
-#include "cerr.h"
-#include "package.h"
-
-char *grstr(WORD word)
+#include "disassemble.h"
+
+/**
+ * @brief 機械コードの出力列
+ */
+int codecol = 32;
+
+/**
+ * @brief ファイルストリームから1ワードを取得する
+ *
+ * @return 取得した1ワード
+ *
+ * @param stream ファイルストリーム
+ */
+WORD fgetword(FILE *stream);
+
+/**
+ * @brief ファイルストリームを1ワード戻す
+ *
+ * @return なし
+ *
+ * @param stream ファイルストリーム
+ */
+void fungetword(FILE *stream);
+
+/**
+ * @brief ファイルストリームから、値が0の連続するWORD数を返す
+ *
+ * @return 値が0の連続するWORD数
+ *
+ * @param stream ファイルストリーム
+ */
+WORD zero_data_cnt(FILE *stream);
+
+/**
+ * @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 word ワード値
+ * @param pradr 次に実行すべき命令語の先頭アドレス
+ */
+void disassemble_dc(WORD word, WORD pradr);
+
+void disassemble_puts_code(int ascol, WORD pradr, int wordc, WORD wordv[])
+{
+ for(int 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 = 0;
+ char *g = NULL;
+ 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 = NULL;
+ char *g1 = NULL;
+ char *g2 = NULL;
+ 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;
+
+ cnt = fprintf(stdout, " DS %-5d ", wcnt);
+ disassemble_puts_code(cnt, pradr, 1, (WORD []){0});
+ for(int i = 0; i < wcnt - 1; i++) {
+ fprintf(stdout, "\n");
+ disassemble_puts_code(0, pradr+1, 1, (WORD []){0});
+ }
+}
+
+WORD fgetword(FILE *stream)
+{
+ WORD aword;
+ fread(&aword, sizeof(WORD), 1, stream);
+ return aword;
+}
+
+void fungetword(FILE *stream)
+{
+ fseek(stream, -sizeof(WORD), SEEK_CUR);
+}
+
+WORD zero_data_cnt(FILE *stream)
{
- char *str = malloc_chk(3 + 1, "grstr.str");
- sprintf(str, "GR%d", word);
- return str;
+ WORD cnt = 0;
+ WORD word = 0;
+
+ while(!feof(stream) && word == 0) {
+ word = fgetword(stream);
+ cnt++;
+ }
+ if(!feof(stream)) {
+ fungetword(stream);
+ }
+ return cnt;
}
-bool disassemble(const char *file)
+bool disassemble_file(const char *file)
{
bool stat = true;
- FILE *fp;
- WORD i = 0, w, cmd, r, x, r1, r2, adr;
+ FILE *fp = NULL;
+ WORD i = 0;
+ WORD word = 0;
+ WORD cmd = 0;
+ WORD zcnt = 0;
CMDTYPE cmdtype = 0;
- char *cmdname, *g1, *g2;
+ const char *cmdname = NULL;
+ bool inst = true;
assert(file != NULL);
if((fp = fopen(file, "rb")) == NULL) {
return false;
}
- create_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を作成 */
+ create_cmdtable(HASH_CODE); /* 命令のコードとタイプがキーのハッシュ表を作成 */
- fprintf(stdout, "MAIN\tSTART\n");
- for(; ;) {
- fread(&w, sizeof(WORD), 1, fp);
- if(feof(fp)) {
- break;
- }
- cmd = w & 0xFF00;
+ fprintf(stdout, "MAIN START\n");
+ for(word = fgetword(fp); !feof(fp); i++, word = fgetword(fp)) {
+ cmd = word & 0xFF00;
cmdname = getcmdname(cmd);
cmdtype = getcmdtype(cmd);
- if(cmd == 0xFF00 || (w != 0 && cmd == 0x0000)) {
- 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);
- fprintf(stdout, "\t%s\t", cmdname);
- if(cmdtype == R_ADR_X) {
- r = (w & 0x00F0) >> 4;
- fprintf(stdout, "%s,", (g1 = grstr(r)));
- FREE(g1);
- }
- fprintf(stdout, "#%04X", adr);
- if((x = w & 0x000F) != 0) {
- fprintf(stdout, ",%s", (g1 = grstr(x)));
- FREE(g1);
+ if(word == 0){
+ if(inst == true) { /* プログラム領域の場合 */
+ disassemble_cmd_r(NONE, "nop", 0, i);
+ } else { /* データ領域の場合 */
+ zcnt = zero_data_cnt(fp);
+ if(zcnt == 1) { /* 1つだけの0はDCとみなす */
+ disassemble_dc(0, i);
+ } else { /* 連続する0はDSとみなす */
+ disassemble_ds(zcnt, i);
+ i += zcnt - 1;
+ }
}
- fprintf(stdout, "\t\t\t\t; #%04X: #%04X #%04X", i, w, adr);
- i += 2;
+ } else if(cmd == 0) {
+ disassemble_dc(word, i);
} else {
- fprintf(stdout, "\t%s", cmdname);
- if(cmdtype == R1_R2) {
- r1 = (w & 0x00F0) >> 4;
- r2 = w & 0x000F;
- fprintf(stdout, "\t%s,%s", (g1=grstr(r1)), (g2=grstr(r2)));
- FREE(g1);
- FREE(g2);
- } else if(cmdtype == R_) {
- r = (w & 0x00F0) >> 4;
- fprintf(stdout, "\t%s", (g1 = grstr(r)));
- FREE(g1);
+ if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
+ disassemble_cmd_adr_x(cmdtype, cmdname, word, fgetword(fp), i++);
+ } else {
+ disassemble_cmd_r(cmdtype, cmdname, word, i);
}
- fprintf(stdout, "\t\t\t\t; #%04X: #%04X", i++, w);
+ inst = (cmd != 0x8100) ? true : false;
}
fprintf(stdout, "\n");
}
- fprintf(stdout, "\tEND\n");
- free_code_cmdtype();
+ fprintf(stdout, " END\n");
+ free_cmdtable(HASH_CODE);
fclose(fp);
return stat;
}
-/**
- * disassembleコマンドのオプション
- */
-static struct option longopts[] = {
- {"version", no_argument, NULL, 'v' },
- {"help", no_argument, NULL, 'h'},
- {0, 0, 0, 0},
-};
-
-/**
- * @brief disassembleコマンドのメイン
- *
- * @return 正常終了時は0、異常終了時は1
- *
- * @param argc コマンドライン引数の数
- * @param *argv[] コマンドライン引数の配列
- */
-int main(int argc, char *argv[])
+void disassemble_memory(WORD start, WORD end)
{
- int opt, stat = 0;
- const char *version = PACKAGE_VERSION, *cmdversion = "disassemble of YACASL2 version %s\n";
- const char *usage = "Usage: %s [-vh] FILE\n";
-
- cerr_init();
- addcerrlist_load();
- addcerrlist_exec();
-
- /* オプションの処理 */
- while((opt = getopt_long(argc, argv, "vh", longopts, NULL)) != -1) {
- switch(opt) {
- case 'v':
- fprintf(stdout, cmdversion, version);
- return 0;
- case 'h':
- fprintf(stdout, usage, argv[0]);
- return 0;
- case '?':
- fprintf(stderr, usage, argv[0]);
- exit(1);
+ WORD cmd = 0;
+ CMDTYPE cmdtype = 0;
+ const char *cmdname = NULL;
+ bool inst = true;
+
+ for(int i = start; i <= end; i++) {
+ cmd = sys->memory[i] & 0xFF00;
+ cmdname = getcmdname(cmd);
+ cmdtype = getcmdtype(cmd);
+ if(sys->memory[i] == 0) {
+ if(inst == true) { /* プログラム領域の場合 */
+ disassemble_cmd_r(NONE, "nop", 0, i);
+ } else { /* データ領域の場合。メモリーでは、DC 0とみなす */
+ disassemble_dc(0, i);
+ }
+ } else if(cmd == 0) {
+ disassemble_dc(sys->memory[i], i);
+ } else {
+ if(cmdtype == R_ADR_X || cmdtype == ADR_X) {
+ disassemble_cmd_adr_x(cmdtype, cmdname, sys->memory[i], sys->memory[i+1], i);
+ i++;
+ } else {
+ disassemble_cmd_r(cmdtype, cmdname, sys->memory[i], i);
+ }
+ inst = (cmd != 0x8100) ? true : false;
}
+ fprintf(stdout, "\n");
}
- if(argv[optind] == NULL) {
- setcerr(211, ""); /* object file not specified */
- fprintf(stderr, "disassemble error - %d: %s\n", cerr->num, cerr->msg);
- exit(1);
- }
- disassemble(argv[optind]); /* プログラム実行 */
- stat = (cerr->num == 0) ? 0 : 1;
- /* エラーの解放 */
- freecerr();
- return stat;
}