📄 caslutil.cpp
字号:
//应当设置一个常量记录变量表的大小(即一共为常量分配多少内存空间)
g_iConstSize = iCurrentOffset;
#ifdef DEBUG_MODE
cout << "---------------------常量标号表------------------------------------" << endl;
uiSize = argVecDst.size();
for (i = 0; i < uiSize; i++)
{
cout << argVecDst[i].strLabelName << " " << argVecDst[i].iOffset;
cout << endl;
}
#endif
return CASL_UTIL_OP_OK;
}
//////////////////////////////////////////////////////////////////
//函数名称:MakeInstructionLabelTable
//函数功能:依据中间代码指令标号表生成目标代码指令标号表,供生成目标代码使用
//入口参数:const LabelMap& argMapSrc---------------------------------中间代码指令标号表
//出口参数:vector<InstructionLabelItem>& argVecDst-------------------生成的目标代码指令标号表
//返回值:CaslUtilStatus----------------操作状态,CASL_UTIL_OP_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-3-18
//修改人员:
//修改日期:
//////////////////////////////////////////////////////////////////
CaslUtilStatus MakeInstructionLabelTable(const LabelMap& argMapSrc, vector<InstructionLabelItem>& argVecDst)
{
//----------------------变量定义部分begins----------------------
InstructionLabelItem instructionLabelItem;
size_t i = 0;
size_t uiSize = 0;
//----------------------变量定义部分ends----------------------
LabelMap::const_iterator itMap = NULL;
//预先清空结果vector
argVecDst.clear();
for (itMap = argMapSrc.begin(); itMap != argMapSrc.end(); itMap++)
{
strcpy(instructionLabelItem.strLabelName, itMap->second.c_str());
instructionLabelItem.iOffset = (itMap->first << 1); //因为COMET机中每条目标指令都是双字长,所以用指令条数编号乘以二
//将生成的指令标号元素放入目标代码指令标号表
argVecDst.push_back(instructionLabelItem);
}
#ifdef DEBUG_MODe
cout << "---------------------指令标号表------------------------------------" << endl;
uiSize = argVecDst.size();
for (i = 0; i < uiSize; i++)
{
cout << argVecDst[i].strLabelName << " " << argVecDst[i].iOffset;
cout << endl;
}
#endif
return CASL_UTIL_OP_OK;
}
//////////////////////////////////////////////////////////////////
//函数名称:MakeObjectCode
//函数功能:生成目标代码
//入口参数:无
//出口参数:无
//返回值:CaslUtilStatus----------------操作状态,CASL_UTIL_OP_OK表示操作成功,其他表示操作失败
//开发人员:杨军
//开发日期:2004-3-18
//修改人员:
//修改日期:
//////////////////////////////////////////////////////////////////
CaslUtilStatus MakeObjectCode()
{
//依据中间代码表,变量标号表,常量标号表,以及指令标号表来生成目标代码
//----------------------变量定义部分begins----------------------
ObjectCode objectCode;
int nIndex = 0;
size_t i = 0;
size_t uiSize = 0;
unsigned char regNumber = 0;
//----------------------变量定义部分ends----------------------
uiSize = g_vecIntermediateCode.size();
//清空上次生成的可视化调试信息
g_vecVisualDebugInfo.clear();
//循环处理每条中间代码,生成其对应的目标代码
for (i = 0; i < uiSize; i++)
{
objectCode.instructionType = g_vecIntermediateCode[i].type;
//清空寄存器,地址数据
//以便于填入新的数据
objectCode.regNumber = 0;
memset(objectCode.address, 0, 2);
//---------------处理操作数1 begins-------------------------------------------------------------
switch (g_vecIntermediateCode[i].operand1.type)
{
case REG_OPERAND:
//将通用寄存器的编号存放在低四位上
objectCode.regNumber = g_vecIntermediateCode[i].operand1.OperandVal.regOperand.regNumber;
break;
case EA_OPERAND:
regNumber = g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.regNumber;
regNumber <<= 4;
//将变址寄存器的编号存放在高四位上
objectCode.regNumber |= regNumber;
//如果地址数据是标号的话,需要查标号表
if (LABEL_EA_ADDRESS == g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.type)
{
//如果标号在变量表中
if ((nIndex = LookUpInVariableLableTable(g_vecVariableLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
{
//(*objectCode.address) = g_vecVariableLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_vecVariableLabel[nIndex].iOffset, objectCode.address);
}
//如果标号在常量表中
else if ((nIndex = LookUpInConstLableTable(g_vecConstLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName))>= 0)
{
//常量表中标号的实际偏移应当是变量标号表的大小再加上
//常量标号表中的标号在常量标号表中的相对偏移大小
//(*objectCode.address) = g_iVariableSize + g_vecConstLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_vecConstLabel[nIndex].iOffset, objectCode.address);
}
else if ((nIndex = LookUpInInstructionLableTable(g_vecInstructionLabel, g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
{
//指令标号表中的实际偏移应当是变量标号表的大小再加上
//常量标号表的大小以后
//再加上指令标号表中的标号在指令标号表中的相对偏移大小
//(*objectCode.address) = g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
//ASSIGN_INT_TO_DBYTE(g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
}
//如果标号也不在指令标号表中,则报错
else
{
//cerr << ;
//return ;
}
}
//如果地址数据是数值的话,直接赋值即可
else if (DEC_EA_ADDRESS == g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.type)
{
//cout << g_szInstructionName[g_vecIntermediateCode[i].type] << "--decimal EA Address:" << g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress;
//cout << endl;
//(*objectCode.address) = g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress;
ASSIGN_INT_TO_DBYTE(g_vecIntermediateCode[i].operand1.OperandVal.eaOperand.address.addressVal.decAddress, objectCode.address);
}
break;
case EMPTY_OPERAND:
//暂时没有一个好的办法来标识空操作数
//目前只有在虚拟机中判断指令是否不需要操作数
//比如在Casl中只有RET指令是不需要操作数的
//objectCode.regNumber = REG_NONE;
//objectCode.address = EMPTY_OPERAND;
break;
default:
break;
}
//---------------处理操作数1 ends-----------------------------------------------------------------
//处理操作数2
//---------------处理操作数2 begins---------------------------------------------------------------
switch (g_vecIntermediateCode[i].operand2.type)
{
case REG_OPERAND:
//将通用寄存器的编号存放在低四位上
objectCode.regNumber = g_vecIntermediateCode[i].operand2.OperandVal.regOperand.regNumber;
break;
case EA_OPERAND:
regNumber = g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.regNumber;
regNumber <<= 4;
//将变址寄存器的编号存放在高四位上
objectCode.regNumber |= regNumber;
//如果地址数据是标号的话,需要查标号表
if (LABEL_EA_ADDRESS == g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.type)
{
//如果标号在变量表中
if ((nIndex = LookUpInVariableLableTable(g_vecVariableLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
{
//(*objectCode.address) = g_vecVariableLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_vecVariableLabel[nIndex].iOffset, objectCode.address);
}
//如果标号在常量表中
else if ((nIndex = LookUpInConstLableTable(g_vecConstLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName))>= 0)
{
//常量表中标号的实际偏移应当是变量标号表的大小再加上
//常量标号表中的标号在常量标号表中的相对偏移大小
//(*objectCode.address) = g_iVariableSize + g_vecConstLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_vecConstLabel[nIndex].iOffset, objectCode.address);
}
else if ((nIndex = LookUpInInstructionLableTable(g_vecInstructionLabel, g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.labelAddress.strLabelName)) >= 0)
{
//指令标号表中的实际偏移应当是变量标号表的大小再加上
//常量标号表的大小以后
//再加上指令标号表中的标号在指令标号表中的相对偏移大小
//(*objectCode.address) = g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset;
ASSIGN_INT_TO_DBYTE(g_iVariableSize + g_iConstSize + g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
//ASSIGN_INT_TO_DBYTE(g_vecInstructionLabel[nIndex].iOffset, objectCode.address);
}
//如果标号也不在指令标号表中,则报错
else
{
//cerr << ;
//return ;
}
}
//如果地址数据是数值的话,直接赋值即可
else if (DEC_EA_ADDRESS == g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.type)
{
//cout << g_szInstructionName[g_vecIntermediateCode[i].type] << "--decimal EA Address:" << g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.decAddress;
//cout << endl;
ASSIGN_INT_TO_DBYTE(g_vecIntermediateCode[i].operand2.OperandVal.eaOperand.address.addressVal.decAddress, objectCode.address);
//cout << "after second operand(decimal address)--" << (int)(*pTemp + *(pTemp + 1) * 0x100)<< endl;
}
break;
case EMPTY_OPERAND:
//暂时没有一个好的办法来标识空操作数
//目前只有在虚拟机中判断指令是否不需要操作数
//比如在Casl中只有RET指令是不需要操作数的
//objectCode.regNumber = REG_NONE;
break;
default:
break;
}
//---------------处理操作数2 ends---------------------------------------------------------------------
g_vecObjectCode.push_back(objectCode);
//为当前指令可以生成调试信息(注意:这里为IN,OUT实际上各生成了三条可视化调试信息记录,但是因为我们在调试器工作的时候
//会进行一定的处理,对于IN,OUT所转换出的三条指令实际上是当成一条指令来执行的,这里就不再特殊处理了!)
g_vecVisualDebugInfo.push_back(InstructionDebugInfo(g_vecIntermediateCode[i].iSrcCodeLineNumber, i));
}
#ifdef DEBUG_MODE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//输出生成的目标代码(不含变量,常量部分)
uiSize = g_vecObjectCode.size();
cout << "目标代码条数:" << uiSize << endl;
for (i = 0; i < uiSize; i++)
{
//输出指令名称
cout << g_szInstructionName[g_vecObjectCode[i].instructionType] << " ";
//注意: 对于JMP, JNZ, JMI, JPZ, JZE, PUSH, POP只能有一个操作数
//而对于RET则没有操作数
//所以在这需要进行分支处理
//如果当前指令是单操作数指令的话
if (g_vecSingleOperandInstructionName.end() != find(g_vecSingleOperandInstructionName.begin(), g_vecSingleOperandInstructionName.end(), g_szInstructionName[g_vecObjectCode[i].instructionType]))
{
//处理操作数1即可
//如果是POP指令的话,使用通用寄存器GR作为操作数
if (!strcmp(g_szInstructionName[g_vecObjectCode[i].instructionType], "POP"))
{
//输出POP的操作数中的寄存器编号
cout << "操作数1(REG): " << (int)(g_vecObjectCode[i].regNumber & 0x0f);
}
//如果是其他的单操作数指令的话
//输入其EA操作数
else
{
regNumber = g_vecObjectCode[i].regNumber & 0xf0;
//cout << "single operand instruction(before right shift): " << (int)regNumber;
regNumber >>= 4;
//cout << "single operand instruction(after right shift): " << (int)regNumber;
cout << "操作数1(EA): XR--" << (int)regNumber << " Address----" << ConvertDByteToInt(g_vecObjectCode[i].address);
}
//如果是其他的单操作数指令的话,使用EA作为操作数
}
//如果当前指令是无操作数指令的话
else if (g_vecNoOperandInstructionName.end() != find(g_vecNoOperandInstructionName.begin(), g_vecNoOperandInstructionName.end(), g_szInstructionName[g_vecObjectCode[i].instructionType]))
{
//目前情况下不需要处理操作数
//以后考虑在目标指令中加入一个标识操作数为空的标志位
}
//是普通的双操作数指令的话
else
{
//在Casl中,对于双操作数指令来说,第一个操作数必然是通用寄存器
//第二个必然是EA,这就给我们的处理带来了很大的方便
//输出操作数1的数据(通用寄存器的编号)
cout << "操作数1(REG): " << (int)(g_vecObjectCode[i].regNumber & 0x0f);
//输出操作数2的数据
//cout << "dobule operand instruction: XR(before shift) " << (int)g_vecObjectCode[i].regNumber << endl;
regNumber = g_vecObjectCode[i].regNumber & 0xf0;
//cout << "dobule operand instruction: XR(after shift) " << (int)regNumber << endl;
regNumber >>= 4;
cout << "操作数2(EA): XR--" << (int)regNumber << " Address----" << ConvertDByteToInt(g_vecObjectCode[i].address);
}
cout << endl;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif
return CASL_UTIL_OP_OK;
}
//////////////////////////////////////////////////////////////////
//函数名称:LookUpInVariableLableTable
//函数功能:在变量标号表中查询有无指定的变量标号记录
//入口参数:vector<VariableLabelItem>& argVec--------------变量标号表
// const CaslString argLabelName------------------待查询的标号名称
//出口参数:无
//返回值:int---------------- >= 0 表示找到的指定的标号记录在变量标号表中的编号,< 0 表示未找到
//开发人员:杨军
//开发日期:2004-3-18
//修改人员:
//修改日期:
//////////////////////////////////////////////////////////////////
int LookUpInVariableLableTable(vector<VariableLabelItem>& argVec, const CaslString argLabelName)
{
//----------------------变量定义部分begins----------------------
size_t i = 0;
size_t uiSize =0;
//----------------------变量定义部分ends----------------------
uiSize = argVec.size();
for (i = 0; i < uiSize; i++)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -