在用logisim初步畫完CPU電路后,配合educoder調試電路。提交代碼到educoder后,后台會檢測錯誤信息,根據報錯信息中的周期數或者PC值,可以找到錯誤的指令機器碼。
但是機器碼太抽象,因此使用下面的程序將指令機器碼翻譯成指令名稱,進而繼續調試電路。
/*
32位MIPS指令翻譯器
輸入一條16進制的指令
輸出該指令的詳細信息
*/
#include<iostream>
#include<string>
#include<cctype>
#include<bitset>
#include<map>
using namespace std;
typedef unsigned int IRType; //存儲32位指令
struct INST{
string name;
string type;
string func;
};
//24條MIPS指令
map<string, INST> transTable = { //can not be const
{"000000000000",{ .name="sll", .type="R", .func="邏輯左移" }},
{"000000000011",{ .name="sra", .type="R", .func="算術右移" }},
{"000000000010",{ .name="srl", .type="R", .func="邏輯右移" }},
{"000000100000",{ .name="add", .type="R", .func="符號加" }},
{"000000100001",{ .name="addu", .type="R", .func="無符號加" }},
{"000000100010",{ .name="sub", .type="R", .func="符號減" }},
{"000000100100",{ .name="and", .type="R", .func="與" }},
{"000000100101",{ .name="or", .type="R", .func="或" }},
{"000000100111",{ .name="nor", .type="R", .func="或非" }},
{"000000101010",{ .name="slt", .type="R", .func="比較大小,小於則寄存器置1(有符號)" }},
{"000000101011",{ .name="sltu", .type="R", .func="比較大小,小於則寄存器置1(無符號)" }},
{"000000001000",{ .name="jr", .type="J", .func="跳轉至寄存器" }},
{"000000001100",{ .name="syscall", .type="SYSCALL", .func="系統調用" }},
{"000010" ,{ .name="j", .type="J", .func="跳轉" }},
{"000011" ,{ .name="jal", .type="J", .func="跳轉並鏈接" }},
{"000100" ,{ .name="beq", .type="I", .func="相等時跳轉" }},
{"000101" ,{ .name="bne", .type="I", .func="不等時跳轉" }},
{"001000" ,{ .name="addi", .type="I", .func="符號加立即數" }},
{"001100" ,{ .name="andi", .type="I", .func="與立即數" }},
{"001001" ,{ .name="addiu", .type="I", .func="無符號立即數加法" }},
{"001010" ,{ .name="slti", .type="I", .func="比較大小,小於立即數則寄存器置1(有符號)" }},
{"001101" ,{ .name="ori", .type="I", .func="或立即數" }},
{"100011" ,{ .name="lw", .type="I", .func="內存加載字到寄存器堆" }},
{"101011" ,{ .name="sw", .type="I", .func="寄存器存儲字到內存" }}
};
string HexToBin( string irHex );
int main()
{
string irHex, irBin;
string opCode, funct;
cout << "請輸入32位16進制指令:(如12200001)" << endl;
while( cin >> irHex ){
irBin = HexToBin(irHex);
cout << "bianry instruction: " << irBin << endl; //test
opCode = irBin.substr(0,6); //不包括最后一位
funct = irBin.substr(26,-1);
if( transTable.find(opCode+funct) != transTable.end() ){
cout << "name : " << transTable[(opCode+funct)].name << endl;
cout << "type : " << transTable[(opCode+funct)].type << " | "
"function : " << transTable[(opCode+funct)].func <<endl;
}
else if( transTable.find(opCode) != transTable.end() ){
cout << "name : " << transTable[(opCode)].name << endl;
cout << "type : " << transTable[(opCode)].type << " | "
"function : " << transTable[(opCode)].func <<endl;
}
else{
cout << "this instruction isn't included." << endl;
}
}
return 0;
}
string HexToBin( string irHex )
{
const string numbers = "0123456789";
string irBin;
IRType irDec = 0;
for( string::iterator itr = irHex.begin(); itr != irHex.end(); itr++ ){
irDec *= 16;
if( numbers.find(*itr) != string::npos ){
irDec += ( (*itr) - '0' );
}else{
( *itr ) = tolower(*itr);
irDec += ( (*itr) - 'a' + 10 );
}
}
//cout << irDec << endl; //test
irBin = 1;
irBin = bitset<sizeof(IRType)*8>((int)irDec).to_string();
return irBin;
}