?? tm.cpp
字號:
}
return temp;
} /* getWord */
/************************************************************/
/* 函數名 skipCh */
/* 功 能 字符空過函數 */
/* 說 明 如果當前位置上字符為函數指定的字符,則空過該字符, */
/* 函數返回TRUE;否則函數返回FALSE */
/************************************************************/
int skipCh ( char c )
{ int temp = FALSE;
/* 當前位置上字符為函數指定字符c */
if ( nonBlank() && (ch == c) )
{ getCh(); /* 空過當前字符c,取下一字符 */
temp = TRUE; /* 空過指定字符c,函數返回TRUE */
}
return temp;
} /* skipCh */
/************************************/
/* 函數名 atEOL */
/* 功 能 行結束判斷函數 */
/* 說 明 當前行是否結束的判斷函數 */
/************************************/
int atEOL(void)
{ return ( ! nonBlank ()); /* 如果當前行中沒有非空字符,則函數返回TRUE */
} /* atEOL */
/****************************************************/
/* 函數名 error */
/* 功 能 錯誤處理函數 */
/* 說 明 函數輸出錯誤行號,指令地址標號和錯誤信息 */
/****************************************************/
int error( char * msg, int lineNo, int instNo)
{
/* 輸出錯誤出現位置行號lineNo */
printf("Line %d",lineNo);
/* 輸出錯誤指令地址標號instNo */
if (instNo >= 0) printf(" (Instruction %d)",instNo);
/* 輸出錯誤信息msg */
printf(" %s\n",msg);
return FALSE;
} /* error */
/********************************************************/
/* 函數名 readInstructions */
/* 功 能 指令文件讀入函數 */
/* 說 明 將指令文件中的指令逐條讀入到指令存儲區iMem */
/********************************************************/
int readInstructions (void)
{
OPCODE op; /* 當前指令操作碼 */
int arg1, arg2, arg3; /* 當前指令操作數 */
int loc, regNo, lineNo;
/* 將8個寄存器內容初始化為0 */
for (regNo = 0 ; regNo < NO_REGS ; regNo++)
reg[regNo] = 0 ;
/* dMem為數據存儲區,0地址單元dMem[0]的值賦為數據存儲區高端地址1023 *
* 此數值將在目標程序運行時由程序的先驅指令讀入到mp寄存器中 */
dMem[0] = DADDR_SIZE - 1 ;
/* 將數據存儲數區內除0地址單元外的各單元初始化為0 */
for (loc = 1 ; loc < DADDR_SIZE ; loc++)
dMem[loc] = 0 ;
/* 將指令存儲區中各單元初始化為指令;HALT 0,0,0 */
for (loc = 0 ; loc < IADDR_SIZE ; loc++)
{ iMem[loc].iop = opHALT ;
iMem[loc].iarg1 = 0 ;
iMem[loc].iarg2 = 0 ;
iMem[loc].iarg3 = 0 ;
}
lineNo = 0 ; /* lineNo用于記錄當前代碼指令行號 */
/* 不是指定文件pgm的文件結尾 */
while (! feof(pgm))
{
/* 從指定文件pgm中讀入119個字符到當前代碼行in_Line */
fgets( in_Line, LINESIZE-2, pgm ) ;
inCol = 0 ; /* 當前代碼行in_Line中當前字符位置inCol初始為0 */
lineNo++; /* 當前代碼行行號加1 */
/* 當前代碼行in_Line行結尾字符位置賦給lineLen */
lineLen = strlen(in_Line)-1 ;
/* 如果源行結束字符是'\n',則更換行結束字符為'\0' */
if (in_Line[lineLen]=='\n') in_Line[lineLen] = '\0' ;
/* 源行沒有行結束字符,加上結束字符'\0' */
else in_Line[++lineLen] = '\0';
/* 當前字符不是"*",即不是注釋語句,應該是指令語句 */
if ( (nonBlank()) && (in_Line[inCol] != '*') )
{
/* 當前字符不是數字,報地址錯,并給出行號lineNo */
if (! getNum())
return error("Bad location", lineNo,-1);
/* 將所得數值賦給當前代碼地址標號loc */
loc = num;
/* 代碼地址標號loc超出指令存儲區地址IADDR_SIZE,報錯 */
if (loc > IADDR_SIZE)
return error("Location too large",lineNo,loc);
/* 代碼地址標號loc后面缺少冒號,報缺少冒號錯 */
if (! skipCh(':'))
return error("Missing colon", lineNo,loc);
/* 當前位置不是單詞,報缺少指令操作碼錯 */
if (! getWord ())
return error("Missing opcode", lineNo,loc);
/* 初始查表指針op,op指向操作碼表表首,值為opHALT */
op = opHALT ;
/* 查操作碼表opCodeTab,只比較當前字word中的前四個字符 *
* 因為所有定義的操作碼中,最長操作碼HALT長度只為四 */
while ((op < opRALim)
&& (strncmp(opCodeTab[op], word, 4) != 0) )
op = (enum opcode)(op+1);
/* 當前單詞word中指定的操作碼不在操作碼表opCodeTab中,報非法操作碼錯誤 */
if (strncmp(opCodeTab[op], word, 4) != 0)
return error("Illegal opcode", lineNo,loc);
/* 對查表得到的操作碼值op的尋址模式,進行分類處理 */
switch ( opClass(op) )
{ case opclRR : /* 寄存器尋址模式操作碼 */
/* 第一寄存器操作數錯,非0-7之間數字, *
* 輸出錯誤信息,行號lineNo,代碼地址標號loc */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad first register", lineNo,loc);
/* 將第一操作數arg1賦值為當前數值num */
arg1 = num;
/* 第一操作數后漏掉","分隔符,報錯 */
if ( ! skipCh(','))
return error("Missing comma", lineNo, loc);
/* 第二寄存器操作數錯,非0-7之間數字, *
* 輸出錯誤信息,行號lineNo,代碼地址標號loc */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad second register", lineNo, loc);
/* 將第二個操作數arg2賦值為當前數值num */
arg2 = num;
/* 第二操作數后漏掉","分隔符,報錯 */
if ( ! skipCh(','))
return error("Missing comma", lineNo,loc);
/* 第三寄存器操作數錯,非0-7之間數字,報錯 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad third register", lineNo,loc);
/* 將第三操作數arg3賦值為當前數值num */
arg3 = num;
break;
/* 寄存器-內存尋址模式 *
* 寄存器-立即數尋址模式 */
case opclRM :
case opclRA :
/* 第一寄存器操作數錯,非0-7之間數字,報錯 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS) )
return error("Bad first register", lineNo,loc);
/* 將第一操作數arg1賦值為當前數值num */
arg1 = num;
/* 第一操作數后面漏掉","分隔符,報錯 */
if ( ! skipCh(','))
return error("Missing comma", lineNo,loc);
/* 第二偏移地址操作數錯誤,非數字偏移地址,報錯 */
if (! getNum ())
return error("Bad displacement", lineNo,loc);
/* 將第二偏移地址操作數arg2賦值為當前地址num */
arg2 = num;
/* 第二偏移地址操作數后漏掉"(",或者是","分隔符,報錯 */
if ( ! skipCh('(') && ! skipCh(',') )
return error("Missing LParen", lineNo,loc);
/* 第二寄存器操作數錯,非0-7之間數字,報錯 */
if ( (! getNum ()) || (num < 0) || (num >= NO_REGS))
return error("Bad second register", lineNo,loc);
/* 將第三操作數arg3賦值為當前數值num */
arg3 = num;
break;
}
/* 按代碼地址標號loc將指令存儲到指令存儲區iMem */
iMem[loc].iop = op;
iMem[loc].iarg1 = arg1;
iMem[loc].iarg2 = arg2;
iMem[loc].iarg3 = arg3;
}
}
return TRUE;
} /* readInstructions */
/************************************************/
/* 函數名 stepTM */
/* 功 能 TM機單步執行函數 */
/* 說 明 函數為一條指令解釋執行,完成指令動作. */
/************************************************/
STEPRESULT stepTM (void)
{
/* currentinstruction 用于存儲當前將執行的指令 */
INSTRUCTION currentinstruction ;
int pc ; /* 程序計數器 */
int r,s,t,m ; /* 指令操作數 */
int ok ;
/* pc設置為第7個寄存器reg[7]的值,為程序計數器 */
pc = reg[PC_REG] ;
if ( (pc < 0) || (pc > IADDR_SIZE) )
/* pc的值不是指令存儲區的有效地址,報指令存儲錯,函數返回srIMEM_ERR */
return srIMEM_ERR ;
/* pc的值為有效指令地址,將程序計數器reg[PC_REG]的值加1 */
reg[PC_REG] = pc + 1 ;
/* 從指令存儲區iMem之中取出當前指令 */
currentinstruction = iMem[ pc ] ;
/* 對取出的指令的尋址模式分類處理,初始化各個指令操作數變量 */
switch (opClass(currentinstruction.iop) )
{ case opclRR : /* 寄存器尋址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg2 ;
t = currentinstruction.iarg3 ;
break;
case opclRM : /* 寄存器-內存尋址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg3 ;
m = currentinstruction.iarg2 + reg[s] ;
/* 操作數m非數據存儲區有效地址,報數據存儲錯,函數返回srDMEM_ERR */
if ( (m < 0) || (m > DADDR_SIZE))
return srDMEM_ERR ;
break;
case opclRA : /* 寄存器-立即數尋址模式 */
r = currentinstruction.iarg1 ;
s = currentinstruction.iarg3 ;
m = currentinstruction.iarg2 + reg[s] ;
break;
} /* case */
/* 對將執行指令的操作碼值進行分類處理,輸出指令信息, *
* 完成指令動作,返回相應結果狀態 */
switch ( currentinstruction.iop)
{
/******************** RR指令 ******************/
/* 格式化屏幕顯示HALT(停止)指令,返回狀態srHALT(停止) */
case opHALT :
printf("HALT: %1d,%1d,%1d\n",r,s,t);
return srHALT ;
/**********************************************/
case opIN :
do
{
/* 屏幕顯示用戶提示信息,提示用戶為指令輸入數值 */
printf("Enter value for IN instruction: ") ;
/* 刷新標準輸入stdin流和標準輸出stdout流 */
fflush (stdin);
fflush (stdout);
/* 從標準輸入流stdin取得用戶輸入的數值,送入緩沖器in_Line */
gets(in_Line);
/* 取得用戶輸入數值的實際長度lineLen */
lineLen = strlen(in_Line) ;
inCol = 0;
/* 如從緩沖器in_Line中成功取得數字,則ok為TRUE */
ok = getNum();
/* 用戶輸入的不是數字,報非法IN指令輸入錯誤 */
if ( ! ok ) printf ("Illegal value\n");
/* 將輸入的數值num送入IN指令操作數r指定的寄存器reg[r] */
else reg[r] = num;
}
/* 如果用戶輸入不合法,重復要求用戶輸入,直到輸入合法數值 */
while (! ok);
break;
/**********************************************/
/* 屏幕顯示OUT指令執行的結果信息 */
case opOUT :
printf ("OUT instruction prints: %d\n", reg[r] ) ;
break;
/**********************************************/
/* 完成ADD指令操作 */
case opADD : reg[r] = reg[s] + reg[t] ; break;
/**********************************************/
/* 完成SUB指令操作 */
case opSUB : reg[r] = reg[s] - reg[t] ; break;
/**********************************************/
/* 完成MUL指令操作 */
case opMUL : reg[r] = reg[s] * reg[t] ; break;
/**********************************************/
case opDIV :
/* 對于除法指令,若除數為0,則報除零錯誤, *
* 并返回srZERODIVIDE;否則,完成除法操作 */
if ( reg[t] != 0 ) reg[r] = reg[s] / reg[t];
else return srZERODIVIDE ;
break;
/***************** RM 指令 ********************/
/* 將數據存儲區dMem中的數據載入到寄存器reg[r] */
case opLD : reg[r] = dMem[m] ; break;
/**********************************************/
/* 將寄存器reg[r]中的數據寫入到數據存儲區dMem */
case opST : dMem[m] = reg[r] ; break;
/***************** RA 指令 ********************/
/* 將寄存器reg[r]賦值為操作數m的值 */
case opLDA : reg[r] = m ; break;
/**********************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -