//■仮想マシンのアセンブラとエミュレータ // //(1) 機械語の種類(以下の6種類があります) // // @タイプ0(SVC命令用) // ┏━━━━━━━━━━━┯━━━━━━━━━━━┓ // ┃           │           ┃ SVC種別を指定します。 // ┃           │           ┃  // ┃           │           ┃   SVC 15 // ┃   命令コード   │  詳細指定     ┃ // ┃       │           ┃ と記述すると, // ┃           │           ┃ 詳細指定に15が入ります。 // ┃           │           ┃ // ┃           │           ┃  // ┃           │ ┃  // ┃    8 bits    │ 8 bits ┃ // ┗━━━━━━━━━━━┷━━━━━━━━━━━┛ // Aタイプ1(分岐命令用相対アドレス指定) // ┏━━━━━━━━━━━┯━━━━━━━━━━━┓ // ┃           │           ┃ この命令の次の番地からの // ┃           │           ┃ 相対アドレスを示します。 // ┃           │           ┃ -128〜127までの値を // ┃   命令コード   │  相対アドレス   ┃ 2の補数で表現します。 // ┃       │           ┃ // ┃           │    指定     ┃  BR 0   // ┃           │           ┃ // ┃           │           ┃ はNOP(何もしない)命令と // ┃           │ ┃ 同じコードになります。 // ┃    8 bits    │ 8 bits ┃ // ┗━━━━━━━━━━━┷━━━━━━━━━━━┛ // Bタイプ2(小さな整数の直接値指定用) // ┏━━━━━━━━━━━┯━━━┯━━━━━━━┓ // ┃           │   │ ┃ 小さな整数をレジスタに入れたり、 // ┃           │   │       ┃ 直接演算をするときの形式です。 // ┃           │ レ │       ┃  // ┃   命令コード   │ ジ │ 小さな   ┃ -16〜17の値を2の補数で表現します。 // ┃       │ ス │       ┃ // ┃           │ タ │  整数    ┃  LI 1,7   // ┃           │   │       ┃ // ┃           │   │        ┃ では,レジスタ1に7が設定されます。 // ┃           │ │ ┃  // ┃    8 bits    │ 3bits│ 5 bits ┃ // ┗━━━━━━━━━━━┷━━━┷━━━━━━━┛ // Cタイプ3 // ┏━━━━━━━━━━━┯━━━┯━━━┯━┯━┓ // ┃           │   │   │レ│レ┃ // ┃           │   │   │ジ│ジ┃ 間接指定は1bit。 // ┃           │ レ │ レ │ス│ス┃ アセンブラ的には @R2と記述する // ┃   命令コード   │ ジ │ ジ │タ│タ┃ // ┃       │ ス │ ス │1│2┃   MOV 4,@2 // ┃           │ タ │ タ │の│の┃ // ┃           │ 1 │ 2 │間│間┃ では、レジスタ2が指す番地の // ┃           │ │   │接│接┃ 内容をレジスタ4にロードする。 // ┃           │ (R1) │ (R2) │指│指┃ // ┃    8 bits    │3bits │3bits │定│定┃ // ┗━━━━━━━━━━━┷━━━┷━━━┷━┷━┛ // Dタイプ4(分岐用/レジスタ退避・復帰用2語命令) // ┏━━━━━━━━━━━┯━━━┯━━━┯━┯━┳━━━━━━━━━━━┯━━━━━━━━━━━┓ // ┃           │   │  イ│ │イ┃           │           ┃ // ┃           │   │  ン│ │ン┃           │           ┃ // ┃           │   │ レデ│間│デ┃           │           ┃ // ┃   命令コード   │(空き)│ ジッ│接│ッ┃                       ┃ // ┃       │   │ スク│指│ク┃       番 地 指 定         ┃VC // ┃           │   │ タス│定│ス┃                       ┃ // ┃           │   │   │ │指┃           │           ┃ // ┃           │ │   │ │定┃           │           ┃ // ┃           │ │ (R2) │ │有┃         │           ┃ // ┃    8 bits    │3bits │3bits │ │効┃          16 bits          ┃ // ┗━━━━━━━━━━━┷━━━┷━━━┷━┷━┻━━━━━━━━━━━┷━━━━━━━━━━━┛ // 例えば「JM AAA」はAAAという番地にジャンプするが、 「JM AAA(3)」はAAAという番地とレジスタの内容 //   が加算された番地にジャンプする。「JM @AAA」と記述すると、AAAの番地に入っている値の番地に //    ジャンプする。 // // // Eタイプ5(一般の2語命令 // ┏━━━━━━━━━━━┯━━━┯━━━┯━┯━┳━━━━━━━━━━━┯━━━━━━━━━━━┓ // ┃           │   │  イ│ │イ┃           │           ┃ // ┃           │ レ │  ン│ │ン┃           │           ┃ // ┃           │ ジ │ レデ│間│デ┃           │           ┃ // ┃   命令コード   │ ス │ ジッ│接│ッ┃                       ┃ // ┃       │ タ │ スク│指│ク┃       番 地 指 定         ┃VC // ┃           │   │ タス│定│ス┃                       ┃ // ┃           │   │   │ │指┃           │           ┃ // ┃           │ │   │ │定┃           │           ┃ // ┃           │ │ (R2) │ │有┃         │           ┃ // ┃    8 bits    │3bits │3bits │ │効┃          16 bits          ┃ // ┗━━━━━━━━━━━┷━━━┷━━━┷━┷━┻━━━━━━━━━━━┷━━━━━━━━━━━┛ // //(2) アセンブラの書式 // @ラベル     8 文字以内の文字列です。 // Aオペレーション 4 文字以内のニーモニックでオペレーションを記述します。 // Bオペランド   2 個以上のオペランドを指定する必要があるときは、コンマで区切ります。 // 1 個のオペランドは次のいずれかです。 // ・レジスタ番号(直接指定。0〜7で指定) // ・値または名前(直接指定) // ・間接指定(直接指定の前に@を付けます) // (例) @ABC ABCに格納されている値がアドレスになります。 // ・インデックス指定(直接指定の後に括弧を付けてレジスタ番号を書きます) //    (例) ABC(3) ABCのアドレスにレジスタ3の内容が加算されたアドレス。 // 関節指定とインデックス指定が両方指定されているときは、インデックス指定が //           先に評価されます。 // (例) @ABC(2) ABCのアドレスにレジスタ2の内容が加算されたアドレスに // 格納されている値がアドレスになります。 // レジスタ番号を指定するオペランドに間接指定(@)が指定されていると // レジスタの内容がアドレスとなります。すなわち、レジスタが示すメモリ番地 // を示します。 // //(3) アセンブラ命令(以下AAAはラベルとします) // // @CONS 定数名を指定します(Constant)。 // (例) AAAA CONS 10 プログラム内のAAAという名前は10と指定されたものとして扱います。 // A* ラベルを記述された部分のアドレスとします。 // (例) AAAA * この箇所のアドレスをAAAとします。 // BDA  領域サイズを指定します(Define Area)。 // AAAA DA 10 この箇所以降に10ワードの領域を確保します。 // CDC この領域に定数を格納します。 // AAAA DC 13 10進数の13を設定します。 // AAAA DC 0x2AB 16進数の02ABを設定します。 // AAAA DC "abcd" 文字列(UNICODE)の"abcd"を設定します。 // 文字列内にC言語と同様のエスケープシーケンスを記述できます。 // ただし,8進数記述はできません。 // また2つの連続する引用符("または')は、1つの引用符とみなされます。 // //(4)機械語命令 // // @タイプ0(間接指定やインデックス指定はない) // SVC <番号> <番号>で指定されるスーパバイザコールです。 // // Aタイプ1(相対番地指定分岐命令。間接指定やインデックス指定はない) // <相対番地> <相対番地>(-128〜127)にで示される条件で分岐します。 // <相対番地>にラベルを指定すると,この命令の次の番地からの // 相対番地が命令コードに入ります。 // したがって,たとえば //  BR 0 // は,何もしないNOP命令と同じ機械語になります。 // // : BR(無条件分岐),BZR(ゼロのとき分岐),BPR(正のとき分岐),BMR(負のとき分岐), // CR(無条件呼出し),BNZR(非ゼロのとき分岐),BNPR(正でないとき(負か0)分岐) // BNMR(負でないとき(正か0)分岐) // // CR命令はレジスタ0に命令の次のアドレスを設定して,当該アドレスに分岐します。 // 分岐先ではR0によってリターン・アドレスを知ることができます。CALL命令をスタック // マシンとして実装するか,IBM流に分岐元に引数アドレスを用意して実装するかは // ソフト設計者に任されます。 // // Bタイプ2(直接定数指定:間接指定やインデックス指定はない) // <レジスタ番号>,<値> // <値>(-16〜15)の小さな値を<レジスタ番号>で示すレジスタに設定,または演算します。 // たとえば, // LI 3,5 // は,レジスタ3に5という値を設定します。たとえば // ADI 3,5 // は,レジスタ3に5という値を加算します。 // : LI(ロード),ADDI(加算),SBI(減算),SLI(左シフト),SRI(右論理シフト),SLA(右算術シフト) //     JR(無条件分岐),JZR(ゼロのとき分岐),JPR(正のとき分岐),JMR(負のとき分岐), // CALR(無条件呼出し),JNZR(非ゼロのとき分岐),JNPR(正でないとき(負か0)分岐) // JNMR(負でないとき(正か0)分岐) // // 分岐命令ではレジスタにレジスタの内容と<値>を加算した結果が分期先になります。 // // Cタイプ3(レジスタ複写:間接指定可能。インデックス指定はない) // <レジスタ番号1>,<レジスタ番号2> // <レジスタ番号2>で示されるレジスタの内容を<レジスタ番号1>で示されるレジスタに // 複写または演算します。なお,間接指定が可能ですので,レジスタ番号の先頭に@を // 付けると,その対象はレジスタで示される主記憶内アドレスの内容となります。 //   (例) // MVR 3,5 レジスタ5の内容をレジスタ3に複写。 // MVR 3,@5 レジスタ5で示されるメモリ・アドレスの内容がレジスタ3に入る。 // (タイプ5のLOAD 3,0(5)と結果は同じであるが1語命令である) // MVR @3,5 レジスタ5の内容をレジスタ3で示されるメモリ・アドレスに複写。 // (タイプ5のSTOR 5,0(3)と結果は同じであるが1語命令である) // : MVR(複写),ADR(加算),SBR(減算),SLR(左シフト),SRR(右論理シフト),SLA(右算術シフト) // // Dタイプ4(分岐/レジスタ退避・復元。間接指定,インデックス指定可能) // <番地指定> <番地指定>で示される番地に分岐,全レジスタの内容を退避または復元します。 // 番地指定の先頭に@を付けると間接指定,カッコつきでレジスタ番号を付けると // インデックス指定になります。 //   (例) // JM   AAA AAAに分岐します。 // JMZ  AAA(1) ゼロのときAAA+(レジスタ1の内容)番地に分岐します。 // JMP @AAA 正のときAAA番地の内容で示される番地に分岐します。 // JMM @AAA(1) 負のときAAA+(レジスタ1の内容)番地の内容で示される // 番地に分岐します。 // に分岐します。R 3,@5 レジスタ5で示されるメモリ・アドレスの内容がレジスタ3に入る。 // (タイプ5のLOAD 3,0(5)と結果は同じであるが1語命令である) // MVR @3,5 レジスタ5の内容をレジスタ3で示されるメモリ・アドレスに複写。 // (タイプ5のSTOR 5,0(3)と結果は同じであるが1語命令である) // // : JM(無条件分岐),JMZ(ゼロのとき分岐),JMP(正のとき分岐),JMR(負のとき分岐), // CALL無条件呼出し),JMNZ(非ゼロのとき分岐),JMNP(正でないとき(負か0)分岐) // JMNM(負でないとき(正か0)分岐) // // Eタイプ5(一般演算。第2オペランドに間接指定,インデックス指定可能) // <対象レジスタ>,<番地指定> // <対象レジスタ>で示されるレジスタに<番地指定>で示される番地,またはその内容を // 演算,ロードまたはストアします。第2オペランドで計算されるアドレスを有効アドレス // と呼ぶことにします。 //   (例) // LOAD 1,AAA AAA番地の内容をレジスタ1にロード。 // STOR 2,AAA レジスタ2の内容をAAA番地に格納。 // LODI 3,AAA AAAそのものの値をレジスタ3に設定。 // (LODI 3,@AAAは結果的にはLOAD 3,AAAと同じ) // (例) LOAD 1,100では100番地の内容がレジスタ1に入るが // LODI 1,100では100という値がレジスタ1に入る。 // ADD 1,@AAA AAAに格納されている内容が指す番地の内容を // レジスタ1に加算。 // // ニーモニックの最後にIが付いている命令がImmidiateを示し,値そのものをロード/演算の対象とします。 // // : LODI(番地ロード),ADDI(番地加算),SUBI(番地減算),SFLI(番地分左シフト),SFRI(番地分右論理シフト), // SFAI(番地分右算術シフト),MLI(番地乗算),DVI(番地除算),MDI(番地剰余), // LOAD(ロード),ADD(加算),SUB(減算),SFL(左シフト),SFR(右論理シフト),SFA(算術シフト), // MLT(乗算),DIV(除算),MOD(剰余),STOR(格納),RET(リターン) // //  RET命令は,有効アドレスで示されるメモリ内の内容を指定されたレジスタにロードし、 // レジスタ0で示される番地に復帰します。 // // //(5) 本プログラムの使用方法 // // 実行開始後,例題プログラムが表示されます。 // // 「翻訳」ボタンをクリックすると,アセンブラが実行し,その結果を表示します。 // 第1パスでのコード生成結果と生成された名前表が表示され, // 最後に生成されたコードがダンプリストとして表示されます。 // // 1ステップずつ追いかけたい場合,最初「開始」ボタンをクリックして下さい。 // 先頭の命令にプログラムカウンタがあることが表示されます。 // 上部に状態フラグ,プログラムカウンタ,各レジスタの内容が表示されます。 // // 「逐次」ボタンをクリックすると1命令ずつ実行します。 // 「連続」ボタンをクリックするとタイマー割込みごとに実行します。 // 連続実行中に停止したい場合は「停止」ボタンをクリックして下さい。 // // 実行の速さを変えたいときは,以下の関数のタイマー割込み間隔を変更して下さい。 // // void EmAuto(HWND hw){ // procAssemble(hw);procEmulate(hw); // SetTimer(hw,1,500,NULL);//実行速度を変えるときは,左の500を変更する // timerFlag=true; // } // #include "myWin.h" #define MAXSRC 65531 static HWND hEdit, hEdit2,hEdit3,hLabel;int timerFlag=false; static TCHAR str[]= TEXT("START *\r\n") //TEXT(" JMP ST1 \r\n") //TEXT(" LI 1,-2\r\n") //TEXT(" ADI 1,2\r\n") //TEXT(" LODI 7,R\r\n") TEXT(" SAVR ENDP\r\n") //TEXT("ST1 LODI 1,ENDP\r\n") TEXT(" LODI 1,ENDP\r\n") TEXT(" LI 2,0\r\n") TEXT(" LOAD 5,V\r\n") TEXT("LOOP SUBI 1,1\r\n") TEXT(" MVR 3,5\r\n") TEXT(" MDI 3,10 \r\n") TEXT(" ADDI 3,48 \r\n") TEXT(" STOR 3,0(1) \r\n") TEXT(" ADI 2,1 \r\n") TEXT(" DVI 5,10\r\n") TEXT(" BNZR LOOP\r\n") TEXT(" STOR 1,R\r\n") TEXT(" SVC 1 \r\n") TEXT(" SVC 0 \r\n") TEXT("R DA 1\r\n") TEXT("V DC 12345\r\n") TEXT(" DA 8\r\n") TEXT("ENDP * \r\n") TEXT(" DA 10 \r\n") // TEXT(" DC \"ab\\r\\n \\x611B cdあいうえ\" \r\n") TEXT(" END\r\n"); typedef struct{ int val; int len;TCHAR name[9]; int nref; int PC[128]; int type[128]; int def; } NameTable; #define MEMMAX 1024 #define NAMTABMAX 128 short int MEM[MEMMAX];TCHAR MEMstr[MEMMAX+1][40]; short int CODEtype[256]; static DWORD dwST; LPARAM lpED;static TCHAR msgStr[128]; static TCHAR src[MAXSRC+1];TCHAR Msg[MAXSRC+1]; static TCHAR obj[MAXSRC+1]; static NameTable namTab[NAMTABMAX+1];int Pname=0,PC=0; int status, REG[8], CODE, regFlag1, regFlag2, effAdd1, effAdd2,nextPC, endFlag; typedef struct{ int PC; TCHAR name[10]; }EQU_Value; int pEqu=0; EQU_Value Equ[21]; void nameClear(){ for(int i=0;i<=NAMTABMAX;i++){ namTab[i].def=false; namTab[i].len=0; namTab[i].name[0]=0; namTab[i].nref=0; } } void initDialog(HWND hw, WPARAM wp,LPARAM lp){//ダイアログの初期化 hEdit=GetDlgItem(hw,4002);hEdit2=GetDlgItem(hw,4003); hEdit3=GetDlgItem(hw,4004);hLabel=GetDlgItem(hw,2001); SetWindowText(hEdit,str); for(int i=0;i<=NAMTABMAX;i++) namTab[i].val=-1; } void cutString(TCHAR Msg[], int L){ int i,j; for(i=L,j=0;Msg[i]!=0;i++,j++)Msg[j]=Msg[i]; Msg[j]=0; } void editMsg(HWND hEdit, TCHAR str[]){ GetWindowText(hEdit,Msg,MAXSRC); int L=lstrlen(Msg)+lstrlen(str)-MAXSRC; if(L>0) cutString(Msg, L+1); lstrcat(Msg,str); SetWindowText(hEdit, Msg); } void EmMsg(TCHAR str[]){ editMsg(hEdit3,str); } void errMsg(HWND hw, TCHAR str[],TCHAR name[]){//エラーメッセージ lstrcpy(Msg, TEXT("** Error **")); lstrcat(Msg, str);lstrcat(Msg,TEXT(" (")); lstrcat(Msg,name);lstrcat(Msg,TEXT(")")); MessageBox(hw,Msg,TEXT("Error"),MB_OK); } void errMsg(HWND hw, TCHAR str[],int N){//エラーメッセージ TCHAR DT[50]; wsprintf(DT,TEXT("%d"),N); errMsg(hw,str,DT); } int setNamTab(HWND hw,TCHAR name[], int V){ int i;lstrcpy(namTab[Pname].name,name);namTab[Pname].val=V; for(i=0;lstrcmp(namTab[i].name,name)!=0;i++); if(i!=Pname){ if(!namTab[i].def) { namTab[i].def=true; namTab[i].val=V;} else errMsg(hw,TEXT("Duplicate names"), name); } else if(i=(len-1)){errFlag=true; name[j]='"';break;} if(src[i]==TCHAR('"')&&src[i+1]==TCHAR('"'))name[j++]=src[i++]; else if(src[i]==TCHAR('"')){name[j++]=src[i++];break;} else if(src[i]==TCHAR('\'')&&src[i]==TCHAR('\''))name[j++]=src[i++]; else if(src[i]==TCHAR('\\'))name[j++]=src[i++]; else if(src[i]==TCHAR('\r')){ name[j]=0; errMsg(hw,TEXT("引用符 \" がありません。 (%S)"), name); name[j++]=TEXT('"');name[j++]=0; break; } name[j++]=src[i++]; } } else{ do{ if(j>=len)errFlag=true; else name[j++]=src[i]; i++; }while(src[i]>0x20 && src[i]!=0x8140 && src[i]!=TCHAR('\t')); } if(j>len) j=len; name[j]=0; if(errFlag) errMsg(hw,TEXT("Name length too long (%S)"), name); return i; } int hexaCode(TCHAR ch){//16進数 if(ch>=TCHAR('0') && ch<=TCHAR('9')) return ch-TCHAR('0'); if(ch>=TCHAR('a') && ch<=TCHAR('f')) return ch-TCHAR('a')+10; if(ch>=TCHAR('A') && ch<=TCHAR('F')) return ch-TCHAR('A')+10; return -1; } int escapeChar[][2]={//エスケープ文字表 {TCHAR('n'), TCHAR('\n')},{TCHAR('t'), TCHAR('\t')}, {TCHAR('v'), TCHAR('\v')},{TCHAR('b'), TCHAR('\b')}, {TCHAR('r'), TCHAR('\r')},{TCHAR('f'), TCHAR('\f')} }; int getEscape(TCHAR ch){ for(int i=0;i<6;i++) if(ch==escapeChar[i][0])return escapeChar[i][1]; return ch; } void addDsp(TCHAR str[]){ GetWindowText(hEdit2,obj,MAXSRC);lstrcat(obj,str); SetWindowText(hEdit2,obj); } void dspNon(TCHAR name[], TCHAR op[], TCHAR opr[]){ wsprintf(Msg,TEXT(" %-8s %-8s %-8s\r\n"),name, op,opr); addDsp(Msg); } void msgCopy40(TCHAR str[]){ int i; for(i=0;i<39&& Msg[i]!=0;i++) str[i]=Msg[i]; str[i]=0; } void dspWord(int PC, int V, TCHAR name[], TCHAR op[], TCHAR opr[]){ wsprintf(Msg,TEXT("%-8s %-8s %-8s"),name, op,opr); msgCopy40(MEMstr[PC]);MEMstr[PC+1][0]=0; wsprintf(Msg,TEXT("%04X:%04X "),PC, V); addDsp(Msg);addDsp(MEMstr[PC]);addDsp(TEXT("\r\n")); } void dspWord(int PC, int V, TCHAR name[], TCHAR op[]){ dspWord(PC, V, name, op, TEXT("")); } void dspWord(int PC, int V,int V2, TCHAR name[], TCHAR op[], TCHAR opr[]){ wsprintf(Msg,TEXT("%-8s %-8s %-8s"),name, op,opr); msgCopy40(MEMstr[PC]);MEMstr[PC+1][0]=0; wsprintf(Msg,TEXT("%04X:%04X %04X "),PC, V,V2 &0x0FFFF); addDsp(Msg);addDsp(MEMstr[PC]);addDsp(TEXT("\r\n")); } typedef struct{ TCHAR op[9]; short int code; } CodeData; CodeData type0code[]={ {TEXT("SVC"),0x10},{TEXT("****"),-1} }; CodeData type1code[]={ {TEXT("BR"),0x00},{TEXT("BZR" ),0x01},{TEXT("BPR" ),0x02},{TEXT("BMR" ),0x03}, {TEXT("CR"),0x04},{TEXT("BNZR"),0x05},{TEXT("BNPR"),0x06},{TEXT("BNMR"),0x07}, {TEXT("****"),-1} }; CodeData type2code[]={ {TEXT("LI"),0x20},{TEXT("ADI"),0x21},{TEXT("SBI"),0x22},{TEXT("SLI"),0x23}, {TEXT("SRI"),0x24},{TEXT("SAI"),0x25}, {TEXT("JR"),0x40},{TEXT("JZR"),0x41},{TEXT("JPR"),0x42},{TEXT("JMR"),0x43}, {TEXT("CALR"),0x44},{TEXT("JNZR"),0x45},{TEXT("JNPR"),0x46},{TEXT("JNMR"),0x47}, {TEXT("****"),-1} }; CodeData type3code[]={ {TEXT("MVR"),0x50},{TEXT("ADR"),0x51},{TEXT("SBR"),0x52},{TEXT("SLR"),0x53}, {TEXT("SRR"),0x54},{TEXT("SAR"),0x55}, {TEXT("****"),-1} }; CodeData type4code[]={ {TEXT("JM") ,0x80},{TEXT("JMZ"),0x81},{TEXT("JMP"),0x82},{TEXT("JMM"),0x83}, {TEXT("CALL"),0x84},{TEXT("JMNZ"),0x85},{TEXT("JMNP"),0x86},{TEXT("JMNM"),0x87}, {TEXT("LODR"),0x88},{TEXT("SAVR"),0x89}, {TEXT("****"),-1} }; CodeData type5code[]={ {TEXT("LODI"),0x90},{TEXT("ADDI"),0x91},{TEXT("SUBI"),0x92},{TEXT("SFLI"),0x93}, {TEXT("SFRI"),0x94},{TEXT("SFAI"),0x95}, {TEXT("MLI" ),0x98},{TEXT("DVI" ),0x99},{TEXT("MDI" ),0x9A}, {TEXT("LOAD"),0xA0},{TEXT("ADD" ),0xA1},{TEXT("SUB"),0xA2},{TEXT("SFL"),0xA3}, {TEXT("SFR" ),0xA4},{TEXT("SFA" ),0xA5}, {TEXT("MLT" ),0xA8},{TEXT("DIV" ),0xA9},{TEXT("MOD" ),0xAA}, {TEXT("STOR"),0xC0},{TEXT("RET"),0xC1}, {TEXT("****"),-1} }; int codeCheck(CodeData table[], TCHAR op[]){ for(int i=0; table[i].code>=0;i++) if(lstrcmp(table[i].op,op)==0)return table[i].code; return -1; } int numCheck(HWND hw,TCHAR opr[]){ int num=0; int iflag=false; for(int i=0; opr[i];i++){ if(opr[i]==TCHAR('-')) iflag=1; else if(opr[i]>=TCHAR('0')&& opr[i]<=TCHAR('9')) num=num*10+opr[i]-TCHAR('0'); else if(opr[i]!=TCHAR('+')){ errMsg(hw,TEXT("Irregular Character"), opr); return num; } } if(iflag) num=-num; return num; } int nameCheck(HWND hw,TCHAR opr[]){ for(int i=0; opr[i];i++){ if(opr[i]!=TCHAR('_')&& (opr[i]TCHAR('9'))&& (opr[i]TCHAR('Z'))&& (opr[i]TCHAR('z'))){ errMsg(hw, TEXT("Irregular Character"), opr); return 1; } } return 0; } void setCodeNum(HWND hw,TCHAR name[], TCHAR op[], TCHAR opr[], int num, int code){ if(num<-128 || num>127) errMsg(hw,TEXT("Short Address Error Character"), num); num=code<<8 | (num & 0x00FF);//リトルエンディアン上でビックエンディアン dspWord(PC, num, name, op, opr); MEM[PC++]=num; } void setCodeNum(HWND hw,TCHAR name[], TCHAR op[], TCHAR opr[], int num, int num1, int code){ num=code<<8 | (num & 0x00FF);//リトルエンディアン上でビックエンディアン dspWord(PC, num,num1, name, op, opr); MEM[PC++]=num;MEM[PC++]=num1; } void procConst(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ int num; if(opr[0]==TCHAR('-')||opr[0]==TCHAR('+')|| (opr[0]>=TCHAR('0')&& opr[0]<=TCHAR('9'))){ num=numCheck(hw,opr);int ID=refNamTab(hw, name); if(ID>=0) namTab[ID].val=num; dspNon(name,op,opr); } } void setReffer(int ID,int type){ namTab[ID].type[namTab[ID].nref]=type; namTab[ID].PC[namTab[ID].nref]=PC; namTab[ID].nref++; } int getNum(HWND hw, TCHAR opr[],int type){ if(opr[0]==0)return 0; if(opr[0]==TCHAR('-')||opr[0]==TCHAR('+')|| (opr[0]>=TCHAR('0')&& opr[0]<=TCHAR('9'))) return numCheck(hw,opr); if(opr[0]==TCHAR('_')|| (opr[0]>=TCHAR('A')&& opr[0]<=TCHAR('Z'))|| (opr[0]>=TCHAR('a')&& opr[0]<=TCHAR('z'))){ if(nameCheck(hw, opr))return 0; int ID; if((ID=refNamTab(hw,opr))>=0) { if(namTab[ID].def) return namTab[ID].val; setReffer(ID,type); return 0; } else { ID=setNamTab(hw,opr,type); namTab[ID].def=false; } setReffer(ID,type); return 0; } else errMsg(hw,TEXT("Irregular Character"), opr); return 0; }int getNum(HWND hw, TCHAR opr[]){ if(opr[0]==0)return 0; if(opr[0]==TCHAR('-')||opr[0]==TCHAR('+')|| (opr[0]>=TCHAR('0')&& opr[0]<=TCHAR('9'))) return numCheck(hw,opr); if(opr[0]==TCHAR('_')|| (opr[0]>=TCHAR('A')&& opr[0]<=TCHAR('Z'))|| (opr[0]>=TCHAR('a')&& opr[0]<=TCHAR('z'))){ if(nameCheck(hw, opr))return 0; int ID; if((ID=refNamTab(hw,opr))>=0) return namTab[ID].val; errMsg(hw,TEXT("Undefined Name"), opr); } else errMsg(hw,TEXT("Irregular Character"), opr); return 0; } void procDA(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[]){ int num=getNum(hw, opr); wsprintf(Msg,TEXT("%-8s %-8s %-8s"),name, op,opr); msgCopy40(MEMstr[PC]);MEMstr[PC+1][0]=0; wsprintf(Msg,TEXT("%04X:0000 "),PC); addDsp(Msg);addDsp(MEMstr[PC]);addDsp(TEXT("\r\n")); MEM[PC++]=0; for(int i=1;i=0)k=k*16+h; str[j++]=k; } else {str[j++]=getEscape(opr[i+1]);i+=2;} } else str[j++]=opr[i++]; } str[j]=0; wsprintf(Msg,TEXT("%-8s %-8s %-8s"),name, op,opr); msgCopy40(MEMstr[PC]);MEMstr[PC+1][0]=0; wsprintf(Msg,TEXT("%04X:%04X %c "),PC, str[0], str[0]); addDsp(Msg);addDsp(MEMstr[PC]);addDsp(TEXT("\r\n")); MEM[PC++]=str[0]; for(i=1;i=TCHAR('0') && opr[0]<=TCHAR('9')) num=getNum(hw,opr); else { int ID;if((ID=refNamTab(hw,opr))<0) return; if(namTab[ID].def) num=namTab[ID].val; else{ setReffer(ID,8); num=0;} } wsprintf(Msg,TEXT("%-8s %-8s %-8s"),name, op,opr); msgCopy40(MEMstr[PC]);MEMstr[PC+1][0]=0; wsprintf(Msg,TEXT("%04X:%04X "),PC,num); addDsp(Msg);addDsp(MEMstr[PC]);addDsp(TEXT("\r\n")); MEM[PC++]=num; } void procType0(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code, int flag){ int num; if(opr[0]==TCHAR('-')||opr[0]==TCHAR('+')|| (opr[0]>=TCHAR('0')&& opr[0]<=TCHAR('9'))){ num=numCheck(hw,opr); setCodeNum(hw,name, op,opr, num, code); } else if(opr[0]==TCHAR('_')|| (opr[0]>=TCHAR('A')&& opr[0]<=TCHAR('Z'))|| (opr[0]>=TCHAR('a')&& opr[0]<=TCHAR('z'))){ if(nameCheck(hw, opr))return; int ID;if((ID=refNamTab(hw,opr))<0) return; if(flag) setCodeNum(hw,name, op,opr, namTab[ID].val, code); else if(namTab[ID].def){ num=(namTab[ID].val-(PC+1)); setCodeNum(hw,name, op,opr, num, code); } else{ setReffer(ID,1); dspWord(PC, code, name, op, opr); MEM[PC++]=code; } } else errMsg(hw, TEXT("Irregular Character"), opr); } void procType0(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ procType0(hw,name, op, opr, code,true); } void procType1(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ procType0(hw,name, op, opr, code, false); } void sepOpr(TCHAR opr[], TCHAR opr1[], TCHAR opr2[]){ int i,j;opr1[0]=opr2[0]=0; for(i=0;opr[i]!=0 && opr[i]!=TCHAR(',');i++)opr1[i]=opr[i]; opr1[i]=0; if(opr[i]==TCHAR(','))i++; for(j=0;opr[i]!=0;i++,j++)opr2[j]=opr[i]; opr2[j]=0; } void procType2(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ TCHAR opr1[40],opr2[40];sepOpr(opr, opr1, opr2); int num, num1=getNum(hw, opr1),num2=getNum(hw, opr2,2); if(num1>7) errMsg(hw,TEXT("Irregular Value"), opr1); if(num2<-16 || num2>15) errMsg(hw,TEXT("Irregular Value"), opr2); num=(num1<<5 |(num2 & 0x1F)) & 0xFF; setCodeNum(hw,name, op,opr, num, code); } void procType3(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ TCHAR opr1[40],opr2[40];sepOpr(opr, opr1, opr2); int num, num1,num2, if1=0, if2=0; if(opr1[0]!=TCHAR('@'))num1=getNum(hw, opr1); else {if1=1; num1=getNum(hw, &opr1[1]);} if(opr2[0]!=TCHAR('@'))num2=getNum(hw, opr2); else {if2=1; num2=getNum(hw, &opr2[1]);} if(num1>7) errMsg(hw,TEXT("Irregular Value"), opr1); if(num2>7) errMsg(hw,TEXT("Irregular Value"), opr2); num=(num1<<5 |(num2 <<2)|(if1<<1)| if2) & 0xFF; setCodeNum(hw,name, op,opr, num, code); } int sepOpr2(HWND hw,TCHAR opr[], TCHAR opr1[], TCHAR opr2[]){ int i,j;opr1[0]=opr2[0]=0; for(i=0;opr[i]!=0 && opr[i]!=TCHAR('(');i++)opr1[i]=opr[i]; opr1[i]=0; int iflag=false; if(opr[i]==TCHAR('(')){i++;iflag=true;} for(j=0;opr[i]!=0 && opr[i]!=TCHAR(')');i++,j++)opr2[j]=opr[i]; opr2[j]=0; if(iflag && opr[i]!=TCHAR(')')) errMsg(hw,TEXT("Not Bracket(\")\")rregular Value"), opr); return iflag; } void procType4(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ TCHAR opr1[40],opr2[40];int if2=sepOpr2(hw, opr, opr1, opr2); int num, num1,num2, if1=0; if(opr1[0]!=TCHAR('@'))num1=getNum(hw, opr1,4); else {if1=1; num1=getNum(hw, &opr1[1],4);} num2=getNum(hw, opr2); if(num1>0xFFFF)errMsg(hw,TEXT(" Irregular Value"), opr1); if(num2>7 || num2<0)errMsg(hw,TEXT("Irregular Value"), opr2); num=((num2 <<2)|(if1<<1)| if2) & 0xFF; setCodeNum(hw,name, op,opr, num, num1, code); } void procType5(HWND hw, TCHAR name[], TCHAR op[], TCHAR opr[], int code){ TCHAR opr1[40],opr2[40],opr3[10],opr4[10];sepOpr(opr, opr1, opr2); int num, num1,num2, if1=0,if2=sepOpr2(hw, opr2, opr3, opr4); num=getNum(hw, opr1); if(opr3[0]!=TCHAR('@'))num1=getNum(hw, opr3,5); else {if1=1; num1=getNum(hw, &opr3[1],5);} num2=getNum(hw, opr4); //if(num1>0xFFFF || num1<0) errMsg(hw,TEXT("Irregular Value"), opr3); if(num2>7 || num2<0) errMsg(hw,TEXT("Irregular Value"), opr1); if(num>7 || num<0)errMsg(hw,TEXT("Irregular Value"), opr1); num=((num <<5)|(num2 <<2)|(if1<<1)| if2) & 0xFF; setCodeNum(hw,name, op,opr, num, num1, code); } int PCend; void memoryDump(){//メモリダンプ wsprintf(Msg,TEXT("Assemble PC=%04X\r\n"),PCend); addDsp(Msg); for(int i=0;i=0x020 && MEM[i]<=0x07E) ch=MEM[i]; if(i==PC) wsprintf(Msg,TEXT("■%04X■■%04X■⇒%-80s<<\r\n"),i, MEM[i]& 0xFFFF, MEMstr[i]); else wsprintf(Msg,TEXT(" %04X : %04X %c |%-80s\r\n"),i, MEM[i]& 0xFFFF, ch, MEMstr[i]); addDsp(Msg); } for(int i=0;i=0x20 ||src[i]==0x8140||src[i]==TCHAR('\t')){ i=procLabel(hw,i,name); i=procOperation(hw,i,op); if(lstrcmp(op,TEXT("END"))==0) break; if(lstrcmp(op,TEXT("NOP"))==0){ dspWord(PC, 0, name, op);MEM[PC++]=0; } else if(lstrcmp(op,TEXT("*"))==0){ if(pEqu<20){ Equ[pEqu].PC=PC;lstrcpy(Equ[pEqu].name,name); pEqu++; } dspNon(name,op,TEXT("")); } else{//オペランド処理 while ((src[i]==0x20||src[i]==0x8140)|| src[i]==TCHAR('\t') ) i++; i=getLabel(hw,i,opr,80); if(lstrcmp(op,TEXT("DA"))==0) procDA(hw, name,op,opr); else if(lstrcmp(op,TEXT("DC"))==0) procDC(hw, name,op,opr); else if(lstrcmp(op,TEXT("CONS"))==0) procConst(hw,name, op, opr, code); else if ((code=codeCheck(type0code,op))>=0) procType0(hw,name, op, opr, code); else if ((code=codeCheck(type1code,op))>=0) procType1(hw,name, op, opr, code); else if ((code=codeCheck(type2code,op))>=0) procType2(hw,name, op, opr, code); else if ((code=codeCheck(type3code,op))>=0) procType3(hw,name, op, opr, code); else if ((code=codeCheck(type4code,op))>=0) procType4(hw,name, op, opr, code); else if ((code=codeCheck(type5code,op))>=0) procType5(hw,name, op, opr, code); else errMsg(hw,TEXT("Irregular Operation (%S)"), op); } while(src[i]>=0x20)i++;//行終りまでオペランド以降を無視 } } } void dspNameTable(){//名前表の表示 for(int i=0;i127) errMsg(hw,TEXT("ddress Overflow"), namTab[i].name); k=namTab[i].PC[j]; MEM[k]=(MEM[k] & 0xFF00) |(D & 0x00FF); } else if(namTab[i].type[j]==2){ D=namTab[i].val; if(D<-16 || D>15){ errMsg(hw,TEXT("Address Overflow"), namTab[i].name); MessageBox(hw,Msg,TEXT("Error"),MB_OK); } k=namTab[i].PC[j]; MEM[k]=(MEM[k] & 0xFFE0) |(D & 0x001F); } else errMsg(hw,TEXT("System Error"), namTab[i].name); } } for(int i=0;i=0)str[0]=CODEtype[i*16+j]+0x30; lstrcat(Msg,str); } } SetWindowText(hEdit3,Msg); */ } void dspStatus(){ TCHAR CC[]=TEXT("ZPM"); wsprintf(Msg, TEXT("STATUS: %C, PC: %04X,") TEXT(" REG 0: %04X, 1: %04X, 2: %04X, 3: %04X,") TEXT(" 4: %04X, 5 :%04X, 6: %04X, 7: %04X"), CC[status], PC,REG[0],REG[1],REG[2],REG[3], REG[4],REG[5],REG[6],REG[7]); SetWindowText(hLabel,Msg); } void EMInit(){ genMemType();status=0;PC=0; for(int i=0;i<8;i++)REG[i]=0; dspStatus();endFlag=false; } int EmFecth(){ CODE=(MEM[PC]>>8)&0x00FF; if(CODEtype[CODE]<0) return 1; switch(CODEtype[CODE]){ case 0: regFlag1=0; effAdd1=MEM[PC]&0x00FF;break; case 1: regFlag1=0; effAdd1=MEM[PC]&0x00FF; if(effAdd1 & 0x80)effAdd1 |= 0xFFFFFF00; effAdd1+=nextPC; break; case 2: regFlag1=1; effAdd1=(MEM[PC]>>5)&7; regFlag2=0; effAdd2=MEM[PC]&0x1F; if(effAdd2 & 0x10)effAdd2 |= 0xFFFFFFE0; break; case 3: regFlag1=1; effAdd1=(MEM[PC]>>5) & 0x7; regFlag2=1; effAdd2=(MEM[PC]>>2) & 0x7; if(MEM[PC]&2){regFlag1=0; effAdd1=REG[effAdd1];} if(MEM[PC]&1){regFlag2=0; effAdd2=REG[effAdd2];} break; case 4: case 5: regFlag1=1; effAdd1=(MEM[PC]>>5) & 7; int INDEX=(MEM[PC]>>2) & 0x07; regFlag2=0; effAdd2=MEM[PC+1]; if(MEM[PC]&1) effAdd2+=REG[INDEX]; if(MEM[PC]&2) effAdd2=MEM[effAdd2]; break; } return 0; } void Em__(){ TCHAR str[128]; wsprintf(str,TEXT("\r\n **Error Operation PC=%04X"),PC); MessageBox(NULL, str, TEXT("Emulater"), MB_OK);endFlag=true; } void EmBR(){ if(regFlag1) nextPC=REG[effAdd1]; else nextPC=effAdd1; } void EmBZR(){if(status==0)EmBR();} void EmBPR(){if(status==1)EmBR();} void EmBMR(){if(status==2)EmBR();} void EmCR(){REG[0]=nextPC;EmBR();} void EmBNZR(){ if(status!=0)EmBR();} void EmBNPR(){if(status!=1)EmBR();} void EmBNMR(){if(status!=2)EmBR();} void EmJM(){nextPC=effAdd2;} void EmJMZ(){if(status==0)EmJM();} void EmJMP(){if(status==1)EmJM();} void EmJMM(){if(status==2)EmJM();} void EmCALL(){REG[0]=nextPC;EmJM();} void EmJMNZ(){if(status!=0)EmJM();} void EmJMNP(){if(status!=1)EmJM();} void EmJMNM(){if(status!=2)EmJM();} void EmPrint(){ TCHAR str[259];int i=0; int AD=REG[1], N=REG[2]; if(N>256)N=256; str[i++]=TCHAR('\r');str[i++]=TCHAR('\n'); while(i<(N+2)) str[i++]=MEM[AD++]; str[i]=0; EmMsg(str); } void EmSVC(){ switch(effAdd1){ case 0:endFlag=true; if(!timerFlag)MessageBox(NULL, TEXT("\r\nプログラム終了"),TEXT("Emulater"), MB_OK); EmMsg(TEXT("\r\nプログラム終了"));break; case 1:EmPrint();break; } } void EmSetSS(int DT){ status=0; if(DT>0)status=1; else if(DT<0) status=2; } void EmLI (){REG[effAdd1] =effAdd2;EmSetSS(REG[effAdd1]);} void EmADI(){REG[effAdd1]+=effAdd2;EmSetSS(REG[effAdd1]);} void EmSBI(){REG[effAdd1]-=effAdd2;EmSetSS(REG[effAdd1]);} void EmSLI(){REG[effAdd1]<<=effAdd2;EmSetSS(REG[effAdd1]);} void EmSRI(){ REG[effAdd1]=(REG[effAdd1]&0x00FFFF)>>effAdd2; EmSetSS(REG[effAdd1]); } void EmSAI(){ if(REG[effAdd1] & 0x8000) REG[effAdd1]|=0xFFFF8000; else REG[effAdd1]&=0x0FFFF; REG[effAdd1]>>=effAdd2; EmSetSS(REG[effAdd1]); } void EmMVR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) REG[effAdd1]=DT; else MEM[effAdd1]=DT; EmSetSS(DT); } void EmADR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) {REG[effAdd1]+=DT;EmSetSS(REG[effAdd1]);} else {MEM[effAdd1]+=DT;EmSetSS(MEM[effAdd1]);} } void EmSBR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) {REG[effAdd1]-=DT;EmSetSS(REG[effAdd1]);} else {MEM[effAdd1]-=DT;EmSetSS(MEM[effAdd1]);} } void EmADDI(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) {REG[effAdd1]+=DT;EmSetSS(REG[effAdd1]);} else {MEM[effAdd1]+=DT;EmSetSS(MEM[effAdd1]);} } void EmSUBI(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) {REG[effAdd1]-=DT;EmSetSS(REG[effAdd1]);} else {MEM[effAdd1]-=DT;EmSetSS(MEM[effAdd1]);} } void EmSLR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) {REG[effAdd1]<<=DT;EmSetSS(REG[effAdd1]);} else {MEM[effAdd1]<<=DT;EmSetSS(MEM[effAdd1]);} } void EmSRR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) { REG[effAdd1]=(REG[effAdd1]& 0x0FFFF)>>DT; EmSetSS(REG[effAdd1]); } else{ MEM[effAdd1]=(MEM[effAdd1]& 0x0FFFF)>>DT; EmSetSS(MEM[effAdd1]); } } void EmSAR(){ int DT=((regFlag2)? REG[effAdd2]:MEM[effAdd2]); if(regFlag1) { if(REG[effAdd1] & 0x8000)REG[effAdd1]|=0xFFFF8000; else REG[effAdd1]&=0x0FFFF; REG[effAdd1]>>=DT; EmSetSS(REG[effAdd1]); } else{ MEM[effAdd1]=(MEM[effAdd1]& 0x0FFFF)<