?? tm.cpp
字號(hào):
/***** 該代碼文件所包含頭文件 *****/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* 宏定義常量TRUE為1 */
#ifndef TRUE
#define TRUE 1
#endif
/* 宏定義常量FALSE為0 */
#ifndef FALSE
#define FALSE 0
#endif
/***************** 常量 *******************/
/* 為大型程序擴(kuò)展,指令存儲(chǔ)區(qū)大小,定義為1024 */
#define IADDR_SIZE 1024
/* 為大型程序擴(kuò)展,數(shù)據(jù)存儲(chǔ)區(qū)大小,定義為1024 */
#define DADDR_SIZE 1024
/* 寄存器數(shù)量,定義為8 */
#define NO_REGS 8
/* PC寄存器,定義為7 */
#define PC_REG 7
/* 目標(biāo)代碼行大小,定義為121 */
#define LINESIZE 121
/* 字大小,定義為20 */
#define WORDSIZE 20
/**************** 類(lèi)型 *******************/
/* 指令尋址模式類(lèi)型 */
typedef enum
{
opclRR, /* 寄存器尋址模式類(lèi)型,操作數(shù)使用寄存器r,s,t */
opclRM, /* 寄存器-內(nèi)存尋址模式類(lèi)型,操作數(shù)使用寄存器r,內(nèi)存地址d+s */
opclRA /* 寄存器-立即數(shù)尋址模式類(lèi)型,操作數(shù)使用寄存器r,立即數(shù)值d+s */
} OPCLASS;
/* 操作指令標(biāo)識(shí)碼類(lèi)型 */
typedef enum opcode{
/************* 寄存器尋址模式指令標(biāo)識(shí)碼 ***************/
opHALT, /* 停止指令:結(jié)束程序執(zhí)行,忽略操作數(shù) */
opIN, /* 輸入指令:將外部變量讀入寄存器,使用第r個(gè)寄存器,忽略s,t參數(shù) */
opOUT, /* 輸出指令:將寄存器的值輸出,使用第r個(gè)寄存器,忽略s,t參數(shù) */
opADD, /* 加法指令:寄存器r的值賦為寄存器s的值與寄存器t的值的和 */
opSUB, /* 減法指令:寄存器r的值賦為寄存器s的值與寄存器t的值的差 */
opMUL, /* 乘法指令:寄存器r的值賦為寄存器s的值與寄存器t的值的積 */
opDIV, /* 除法指令:寄存器r的值賦為寄存器s的值與寄存器t的值的商 */
/* 寄存器尋址模式指令限制標(biāo)志, *
* 操作標(biāo)識(shí)碼枚舉值小于opRRLim的指令均為寄存器尋址模式指令 */
opRRLim,
/************** 寄存器-內(nèi)存尋址模式指令標(biāo)識(shí)碼 ****************/
opLD, /* 載入指令:寄存器r的值賦為地址為d+reg(s)的內(nèi)存單元的值 */
opST, /* 設(shè)置指令:將地址為d+reg(s)的內(nèi)存單元值賦為寄存器r的值 */
/* 寄存器-內(nèi)存尋址模式指令限制標(biāo)志 *
* 操作標(biāo)識(shí)碼枚舉值小于opRMLim且大于opRRLim的均為寄存器-內(nèi)存尋址模式指令 */
opRMLim,
/************* 寄存器-立即數(shù)尋址模式指令標(biāo)識(shí)碼 ****************/
opLDA, /* 載入指令:將寄存器r的值賦為立即數(shù)d與寄存器s的值的和 */
opLDC, /* 載入指令:將寄存器r的值賦為立即數(shù)d,參數(shù)s被忽略 */
opJLT, /* 如果寄存器r的值小于0,將第7個(gè)寄存器的值賦為d+reg(s) *
* 第7個(gè)寄存器為pc程序計(jì)數(shù)寄存器 */
opJLE, /* 如果寄存器r的值小于等于0,將pc寄存器的值賦為d+reg(s) */
opJGT, /* 如果寄存器r的值大于0,將pc寄存器的值賦為d+reg(s) */
opJGE, /* 如果寄存器r的值大于等于0,將pc寄存器的值賦為d+reg(s) */
opJEQ, /* 如果寄存器r的值等于0,將pc寄存器的值賦為d+reg(s) */
opJNE, /* 如果寄存器r的值不等于0,將pc寄存器的值賦為d+reg(s) */
/* 寄存器-立即數(shù)尋址模式指令限制標(biāo)志
* 操作標(biāo)識(shí)碼枚舉值小于opRALim且大于opRMLim的均為寄存器-立即數(shù)尋址模式指令 */
opRALim
} OPCODE;
/************ 指令單步執(zhí)行結(jié)果類(lèi)型 ************/
typedef enum {
srOKAY, /* 正常 */
srHALT, /* 停止 */
srIMEM_ERR, /* 指令存儲(chǔ)錯(cuò) */
srDMEM_ERR, /* 數(shù)據(jù)存儲(chǔ)錯(cuò) */
srZERODIVIDE /* 除數(shù)為零錯(cuò) */
} STEPRESULT;
/* 指令結(jié)構(gòu)類(lèi)型:操作碼,操作數(shù)1,操作數(shù)2,操作數(shù)3 */
typedef struct {
int iop ;
int iarg1 ;
int iarg2 ;
int iarg3 ;
} INSTRUCTION;
/******** 變量 ********/
int iloc = 0 ; /* 指令存儲(chǔ)計(jì)數(shù)指針,初始為0 */
int dloc = 0 ; /* 數(shù)據(jù)存儲(chǔ)計(jì)數(shù)指針,初始為0 */
int traceflag = FALSE; /* 指令執(zhí)行追蹤標(biāo)志,初始為FALSE */
int icountflag = FALSE; /* 指令執(zhí)行計(jì)數(shù)標(biāo)志,初始為FALSE */
/* iMem用于指令存儲(chǔ),為1024長(zhǎng)的指令結(jié)構(gòu)數(shù)組 */
INSTRUCTION iMem [IADDR_SIZE];
/* dMem用于數(shù)據(jù)存儲(chǔ),為1024長(zhǎng)的整數(shù)類(lèi)型數(shù)組 */
int dMem [DADDR_SIZE];
/* reg用于寄存器存儲(chǔ),為8長(zhǎng)的整數(shù)類(lèi)型數(shù)組 */
int reg [NO_REGS];
/* 指令操作碼表,對(duì)應(yīng)尋址模式分為三類(lèi) */
char * opCodeTab[]
= {"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
/* 寄存器尋址模式指令類(lèi)型 */
"LD","ST","????",
/* 寄存器-內(nèi)存尋址模式指令類(lèi)型 */
"LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
/* 寄存器-立即數(shù)尋址模式指令類(lèi)型 */
};
/** 單步執(zhí)行結(jié)果狀態(tài)表 **/
char * stepResultTab[]
= {"OK","Halted","Instruction Memory Fault",
"Data Memory Fault","Division by 0"
};
char pgmName[20]; /* 用于存儲(chǔ)程序文件名 */
FILE *pgm ; /* 程序文件指針 */
char in_Line[LINESIZE] ; /* 用于存儲(chǔ)一行代碼,為121長(zhǎng)的字符數(shù)組 */
int lineLen ; /* in_Line中行結(jié)尾字符位置 */
int inCol ; /* 用于指出在in_Line中的當(dāng)前字符位置 */
int num ; /* 用于存儲(chǔ)當(dāng)前所得數(shù)值 */
char word[WORDSIZE] ; /* 用于存儲(chǔ)當(dāng)前的字,為20長(zhǎng)的字符數(shù)組 */
char ch ; /* 當(dāng)前代碼行中當(dāng)前位置上的字符 */
int done ;
/****************************************************/
/* 函數(shù)名 opClass */
/* 功 能 指令尋址模式分類(lèi)函數(shù) */
/* 說(shuō) 明 該函數(shù)對(duì)給定的指令操作碼枚舉值c進(jìn)行分類(lèi) */
/* 返回指令所屬尋址模式 */
/****************************************************/
int opClass( int c )
{
/* 如果枚舉值c小于opRRLim,則指令為寄存器尋址模式指令類(lèi)型 */
if ( c <= opRRLim) return ( opclRR );
/* 如果枚舉值c小于opRMLim,則指令為寄存器-內(nèi)存尋址模式指令類(lèi)型 */
else if ( c <= opRMLim) return ( opclRM );
/* 為寄存器-立即數(shù)尋址模式指令類(lèi)型 */
else return ( opclRA );
}
/********************************************************/
/* 函數(shù)名 writeInstruction */
/* 功 能 指令輸出函數(shù) */
/* 說(shuō) 明 該函數(shù)將指令存儲(chǔ)區(qū)中指令以指定格式輸出到屏幕 */
/********************************************************/
void writeInstruction ( int loc )
{
/* loc為所要輸出的指令在指令存儲(chǔ)區(qū)中地址,輸出到屏幕 */
printf( "%5d: ", loc) ;
/* 輸出指令地址loc在0-1023有效的指令存儲(chǔ)區(qū)地址范圍之內(nèi) */
if ( (loc >= 0) && (loc < IADDR_SIZE) )
{
/* 輸出地址為loc上的指令操作碼值iMem[loc].iop和第一操作數(shù)iMem[loc].iarg1 */
printf("%6s%3d,", opCodeTab[iMem[loc].iop], iMem[loc].iarg1);
/* 根據(jù)指令的尋址模式分類(lèi)處理 */
switch ( opClass(iMem[loc].iop) )
{
/* 輸出指令為寄存器尋址模式指令,以給定形式輸出操作數(shù)2,操作數(shù)3 */
case opclRR: printf("%1d,%1d", iMem[loc].iarg2, iMem[loc].iarg3);
break;
/* 輸出指令為寄存器-立即數(shù)尋址模式指令,和寄存器-內(nèi)存尋址模式指令 *
* 以給定形式輸出操作數(shù)2,操作數(shù)3 */
case opclRM:
case opclRA: printf("%3d(%1d)", iMem[loc].iarg2, iMem[loc].iarg3);
break;
}
/* 向屏幕輸出換行符 */
printf ("\n") ;
}
} /* writeInstruction */
/****************************************************/
/* 函數(shù)名 getCh */
/* 功 能 字符獲取函數(shù) */
/* 說(shuō) 明 如果當(dāng)前行中字符未讀完,則函數(shù)返回當(dāng)前字符 */
/* 否則,函數(shù)返回空格字符 */
/****************************************************/
void getCh (void)
{
/* 在當(dāng)前代碼行in_Line中,當(dāng)前字符列數(shù)inCol未超過(guò)代碼行實(shí)際長(zhǎng)度lineLen *
* 取得當(dāng)前行中當(dāng)前位置的字符,送入ch */
if (++inCol < lineLen)
ch = in_Line[inCol] ;
/* 如果inCol超出當(dāng)前代碼行長(zhǎng)度范圍,則ch賦為空格 */
else ch = ' ' ;
} /* getCh */
/********************************************************/
/* 函數(shù)名 nonBlank */
/* 功 能 非空字符獲取函數(shù) */
/* 說(shuō) 明 如果成功從當(dāng)前行中取得非空字符,函數(shù)返回TRUE */
/* 否則,函數(shù)返回FALSE */
/********************************************************/
int nonBlank (void)
{
/* 在當(dāng)前代碼行in_Line中,當(dāng)前字符位置inCol中為空格字符 *
* 在當(dāng)前代碼行in_Line中,當(dāng)前字符位置inCol下移,略過(guò)空格 */
while ((inCol < lineLen)
&& (in_Line[inCol] == ' ') )
inCol++ ;
/* 在當(dāng)前代碼行in_Line中,遇到非空字符 */
if (inCol < lineLen)
{
/* 取當(dāng)前字符位置inCol中的字符送入ch, *
* 函數(shù)返回TRUE(已定義為1),ch中得到非空字符 */
ch = in_Line[inCol] ;
return TRUE ; }
/* 當(dāng)前代碼行已經(jīng)讀完,將當(dāng)前字符ch 賦為空格, *
* 函數(shù)返回FALSE(已定義為0),ch中為空格字符 */
else
{ ch = ' ' ;
return FALSE ; }
} /* nonBlank */
/****************************************************************/
/* 函數(shù)名 getNum */
/* 功 能 數(shù)值獲取函數(shù) */
/* 說(shuō) 明 將代碼行中連續(xù)出現(xiàn)的有加減運(yùn)算的數(shù)term合并計(jì)數(shù), */
/* 所的數(shù)值送入為num.如果成功得到數(shù)值,則函數(shù)返回TRUE; */
/* 否則,函數(shù)返回FALSE */
/****************************************************************/
int getNum (void)
{ int sign; /* 符號(hào)因子 */
int term; /* 用于記錄當(dāng)前錄入的局部數(shù)值 */
int temp = FALSE; /* 記錄函數(shù)返回值,初始為假 */
num = 0 ; /* 用于記錄所有加減運(yùn)算后的最終數(shù)值結(jié)果 */
do
{ sign = 1; /* 符號(hào)因子初始為1 */
/* 調(diào)用函數(shù)nonBlank()略過(guò)當(dāng)前位置的空格后, *
* 所得到的當(dāng)前非空字符ch為+或-.(+/-的連續(xù)出現(xiàn)處理) */
while ( nonBlank() && ((ch == '+') || (ch == '-')) )
{ temp = FALSE ;
/* 當(dāng)前字符ch為"-"時(shí),符號(hào)因子sign設(shè)為-1 */
if (ch == '-') sign = - sign ;
/* 取當(dāng)前代碼行中下一字符到當(dāng)前字符ch中 */
getCh();
}
term = 0 ; /* 當(dāng)前錄入的局部數(shù)值初始為0 */
nonBlank(); /* 略過(guò)當(dāng)前位置上的空格 */
/* 當(dāng)前字符ch為數(shù)字,局部數(shù)值的循環(huán)處理 */
while (isdigit(ch))
{ temp = TRUE ; /* 函數(shù)返回值設(shè)為T(mén)RUE,成功得到數(shù)字 */
/* 將字符序列轉(zhuǎn)化為數(shù)值形式,進(jìn)行進(jìn)位累加 */
term = term * 10 + ( ch - '0' ) ;
getCh(); /* 取當(dāng)前代碼行中下一字符到當(dāng)前字符ch中 */
}
/* 將局部數(shù)值帶符號(hào)累加,得到最終數(shù)值num */
num = num + (term * sign) ;
} while ( (nonBlank()) && ((ch == '+') || (ch == '-')) ) ;
return temp;
} /* getNum */
/****************************************************/
/* 函數(shù)名 getWord */
/* 功 能 單詞獲取函數(shù) */
/* 說(shuō) 明 函數(shù)從當(dāng)前代碼行中獲取單詞.如果得到字符, */
/* 則函數(shù)返回TRUE;否則,函數(shù)返回FALSE */
/****************************************************/
int getWord (void)
{
int temp = FALSE; /* 函數(shù)返回值初始為FALSE */
int length = 0; /* 單詞長(zhǎng)度初始為0 */
/* 在當(dāng)前代碼行中成功獲取非空字符ch */
if (nonBlank ())
{
/* 當(dāng)前非空字符ch為字母或數(shù)字 */
while (isalnum(ch))
{
/* 當(dāng)前單詞word未超過(guò)規(guī)定字長(zhǎng)WORDSIZE-1(為單詞結(jié)束字符留一空位) *
* 將當(dāng)前字符ch讀入到單詞末尾 */
if (length < WORDSIZE-1) word [length++] = ch ;
getCh() ; /* 取當(dāng)前代碼行中下一字符 */
}
/* 給當(dāng)前單詞word加入結(jié)束字符 */
word[length] = '\0';
/* 設(shè)置函數(shù)返回值,當(dāng)讀入字word非空的時(shí)候?yàn)門(mén)RUE */
temp = (length != 0);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -