📄 tcwiz2.cpp
字号:
// File : TcWiz2.Cpp
// Implementation of the Translate Block function.
// Implementation file of TcWizard.h
//
#include <dos.h>
#include <stdio.h>
#include <assert.h>
#include <alloc.h>
#include <conio.h>
#include "Disc.h"
#include "TcWizard.h"
#include "Disasm.h"
/*----------------------------------------------------------------------
Wrapper Fn. to find Modified Registers. Only used by IsTernaryOperatorCode.
----------------------------------------------------------------------*/
void TcWizard::FindRegsModified(Byte far *BlockBegin,Sword BlockSize,Byte *RegModified)
{
TranslateBlock(BlockBegin,BlockSize,0,NULL,RegModified,NULL);
}
/*----------------------------------------------------------------------
Wrapper Fn. to find 'Used' registers. Only used by IsTernaryOperatorCode.
----------------------------------------------------------------------*/
void TcWizard::FindRegsUsed(Byte far *BlockBegin,Sword BlockSize,Byte *RegModified,Byte *RegUsed)
{
TranslateBlock(BlockBegin,BlockSize,0,NULL,RegModified,RegUsed);
}
/*----------------------------------------------------------------------
Overloaded Fn. which ignores RegFlags parameter, i.e. not checking which
registers are modified in the code block.
----------------------------------------------------------------------*/
void TcWizard::TranslateBlock(Byte far *BlockBegin,Sword BlockSize,int How,StringList *sList)
{
TranslateBlock(BlockBegin,BlockSize,How,sList,NULL,NULL);
}
/*
[-----------------------------------------------------------------------]
[ TranslateBlock ]
[-----------------------------------------------------------------------]
[ Converts the given block of code into C-code. ]
[ ]
[ BlockBegin - Starting of the code block ]
[ BlockEnd - End of the code fragment ]
[ How - How to store in the StringList ]
[ - as SEPARATE_LINES or COMMA_EXPRESSIONS ]
[ sList - StringList in which the output lines are stored ]
[ RegModified- Array of flags to indicate which registers were ]
[ modified in the given code fragment ]
[ RegUsed - Array of flags to indicate which registers are 'used' ]
[ i.e. accessed. ]
[ (Elements of both RegModified & RegUsed are set to 1 by ]
[ this procedure, and this proc.does not make use of ]
[ these parameters for anything else.) ]
[-----------------------------------------------------------------------]
*/
void TcWizard::TranslateBlock(
Byte far *BlockBegin,
Sword BlockSize,
int How,
StringList *sList,
Byte *RegModified,
Byte *RegUsed
)
{
#define marknotused(Reg) NotUsed[Reg]=1;
#define markused(Reg) NotUsed[Reg]=0;
#define CheckAndOutput(str,how,slist) \
if (!RegModified && !RegUsed) Output(str,how,slist)
#define CheckAndDeletePending(Reg) \
if (!RegModified && !RegUsed) DeletePending(Reg)
#define CheckAndAddPending(str) \
if (!RegModified && !RegUsed) AddPending(str)
#define SetRegModified(Reg) \
if (RegUsed && !RegUsed[Reg]) RegModified[Reg]=1; \
marknotused(Reg)
#define SetRegModified2(Reg) \
if (RegUsed && !RegUsed[Reg]) RegModified[Reg]=2; \
marknotused(Reg)
#define SetRegUsed(Reg) \
if (RegUsed) RegUsed[Reg]=1; \
markused(Reg)
#define CheckAndSetRegUsed(Oper,Data) \
if(Oper==REG_DIRECT && !RegisterVariable(Data)) SetRegUsed(Data);
Byte NotUsed[8+8+4];
memset(NotUsed,0,sizeof(NotUsed));
if (BlockSize<=0) return;
int InstLen;
int val,i,oper;
int row=wherey()+1;
SwitchInfo SwInfo; // Structure used for SWITCH statements.
SwInfo.NumClauses=0;
String s_LineBuffer;
char *LineBuffer = (char *)s_LineBuffer;
Byte far *Inst;
Disasm d;
d.SetCodePtr(CodePtr);
Inst = BlockBegin;
Dword ctr = 0;
String tmp,tmp1,toStr;
#define toString(str) toStr.Copy(str)
InstInfo inst,previnst;
char PrevImmValueStored=0;
Word PrevImmediateValue; // Used in converting 'long-int' code.
Variable v1,v2;
int v2Type;
char *vName;
while(ctr<BlockSize && Inst<ProcEndAddress)
{
// Set the data segment for the next instruction as the usual data segment
// if the previous instruction was not a segment override.
Byte far *DataSegment;
if (inst.Instr!=SEGMENT)
DataSegment = GetDataSegment();
DataSegment = DataSegment;
InstAddr = FP_OFF(Inst);
gotoxy(5,row); printf("Decoding Instruction at address % 4X\r",InstAddr);
d.TraceInst(Inst,InstLen);
inst = d.CurInst;
TranslateTrickyInsts(inst);
LineBuffer[0] = 0;
// Are we moving the return value of any procedure (even after some
// arithmetic operation) to somewhere? If so, delete the corresponding
// pending o/p line. But Make sure that the 2nd operand is a register
if (inst.Operand2 == REG_DIRECT)
CheckAndDeletePending(Regs[inst.Data21]);
// Is it a single operand instruction?
if (inst.Operand1 == REG_DIRECT && inst.Operand2==OPER_UNKNOWN)
CheckAndDeletePending(Regs[inst.Data11]);
// Is the current address given a label in the code?
// If so, print the label.
if (GetLabel(InstAddr,tmp))
{
tmp += ":";
CheckAndOutput(tmp,How,sList);
}
// If this is a SWITCH statement, make necessary arrangements.
if (IsSwitchStatement(InstAddr))
FillSwitchInfo(Inst,inst,SwInfo);
// Find the datatype of the memory operand used in this instruction
// (if any) and register it in the LocalVars/GlobalVars list.
if (inst.Instr!=LEA) // since argument to LEA can be any datatype.
FindAndRegisterDataTypes(inst);
tmp1 = "";
// Now trace the instruction.
switch(inst.Instr)
{
// Segment override.
case SEGMENT: Word Segment = GetReg(inst.Data11).ValueFromHex();
DataSegment = (Byte far *)MK_FP(Segment,0);
break;
case CBW : Regs[REG_AX] = /*toString("(int)") + */GetReg(REG_AL);
SetRegUsed(REG_AL);
break;
case CWD : /*if (strncmp((char *)GetReg(REG_AX),"(int)",5)==0)
strcpy((char *)GetReg(REG_AX),((char *)GetReg(REG_AX))+5);
*/tmp = GetReg(REG_AX);
//Regs[REG_AL] = toString("LOBYTE((long)") + tmp + ")";
Regs[REG_AX] = tmp;
Regs[REG_DX] = toString("HIWORD((long)") + tmp + ")";
SetRegUsed(REG_AX);
break;
case LEA : tmp=GetOperand2(inst);
Regs[inst.Data11] = toString("&") + tmp;
if (RegisterVariable(inst.Data11))
{
sprintf(LineBuffer,"%s = _%s;",Regstr[i],GetRegVarName(inst.Data11));
CheckAndOutput(LineBuffer,How,sList);
}
else SetRegModified(inst.Data11);
break;
case IDIV : case DIV :
switch(inst.Operand1)
{
case REG_DIRECT :
case MEMORY :
case REG_INDIRECT :
case INDEXED_BYTE :
case INDEXED_WORD :
CheckAndSetRegUsed(inst.Operand1,inst.Data11);
SetRegModified(REG_AL);
SetRegModified(REG_AX);
SetRegModified(REG_DX);
tmp=GetOperand1(inst);
if (strncmp(GetReg(REG_AX),"(long)",6)==0)
strcpy((char *)GetReg(REG_AX),((char *)GetReg(REG_AX))+6);
if (inst.operSize1==0)
{
Regs[REG_AL] = toString("(") + GetReg(REG_AX) + \
") / (" + tmp + ")";
}
else
{
tmp1 = toString("(") + GetReg(REG_AX) + ") / (" + \
tmp + ")";
tmp = toString("(") + GetReg(REG_AX) + ") % (" + \
tmp + ")";
Regs[REG_AL] = tmp1;
Regs[REG_AX] = tmp1;
Regs[REG_DX] = tmp;
Regs[REG_DL] = tmp;
}
break;
}
break;
case IMUL : case MUL :
switch(inst.Operand1)
{
case REG_DIRECT :
case MEMORY :
case REG_INDIRECT :
case INDEXED_BYTE :
case INDEXED_WORD :
CheckAndSetRegUsed(inst.Operand1,inst.Data11);
SetRegModified(REG_AL);
SetRegModified(REG_AX);
SetRegModified(REG_DX);
tmp=GetOperand1(inst);
if (inst.operSize1==0)
{
Regs[REG_AX] = toString("(") + GetReg(REG_AL) + \
") * (" + tmp + ")";
}
else
{
tmp = toString("(") + GetReg(REG_AX) + ") * (" + \
tmp + ")";
Regs[REG_AL] = tmp;
Regs[REG_AX] = tmp;
Regs[REG_DX] = toString("HIWORD(") + tmp + ")";
}
break;
}
break;
case NOT : case NEG :
switch(inst.Operand1)
{
case MEMORY :
case REG_INDIRECT :
case INDEXED_BYTE :
case INDEXED_WORD :
tmp = GetOperand1(inst);
ComPlaceForNot:
sprintf(EndOf(LineBuffer),"%s = %c (%s);",(char *)tmp,\
(inst.Instr==NOT)?'~':'-',\
(char *)tmp);
CheckAndOutput(LineBuffer,How,sList);
break;
case REG_DIRECT :
if (RegisterVariable(inst.Data11))
{
tmp=GetRegVarName(inst.Data11);
goto ComPlaceForNot;
}
else
{
Regs[inst.Data11] = toString((inst.Instr==NOT) ? \
"~ (":"- (") + GetReg(inst.Data11) + ")";
SetRegModified(inst.Data11);
SetRegUsed(inst.Data11);
}
break;
}
break;
case CMP : inst.GetVariable(v1,1);
if (IsLongInt(v1) && !IsFirstWordOfLongInt(v1)) break;
inst.GetVariable(v1,2);
if (IsLongInt(v1) && !IsFirstWordOfLongInt(v1)) break;
if (inst.Operand1==REG_DIRECT)
CheckAndDeletePending(GetReg(inst.Data11));
CheckAndSetRegUsed(inst.Operand1,inst.Data11);
CheckAndSetRegUsed(inst.Operand2,inst.Data21);
// if we are just checking the registers modified in this
// part of the code, don't decode the switch statement.
if (!RegModified && !RegUsed)
{
if (InSwitchStatement(SwInfo))
{
if (inst.Operand1!=REG_DIRECT)
{
sprintf(errorStr,"Error in decoding a Switch construct at %X",InstAddr);
ErrorList.Add(errorStr);
break;
}
if (IsSwitchStatement(InstAddr)==C_SWITCH_ORDERED)
{
if (inst.Operand2==IMMEDIATE) tmp=GetOperand1(inst);
else tmp=GetOperand1(inst);
}
else
{
if ((inst.Operand2==INDEXED_BYTE ||
inst.Operand2==INDEXED_WORD) &&
inst.Data21==INDX_BP) tmp=GetOperand2(inst);
else tmp=GetOperand1(inst);
}
sprintf(LineBuffer,"switch(%s)",(char *)tmp);
CheckAndOutput(LineBuffer,How,sList);
CheckAndOutput("{",How,sList);
// skip all code upto the end of the switch statement.
Byte far *tInst = DecodeSwitchStatement(SwInfo,How,sList,FP_OFF(BlockBegin)+BlockSize);
// make adjustments to the counter variables.
ctr += tInst-Inst;
Inst = tInst;
// Just to fool the incrementing code at the end of
// the switch.
ctr -= InstLen;
Inst -= InstLen;
CheckAndOutput("}",How,sList);
break;
}
}
CompareVar.Operand1=GetOperand1(inst);
CompareVar.Operand2=GetOperand2(inst);
break;
case JMP : /*if(IsReturnStatement())
{
tmp = "return ";
if (NotUsed[REG_DX])
{
CheckAndDeletePending(Regs[REG_DX]);
// if DX = HIWORD(some expression), ignore it.
if (strncmp(Regs[REG_DX],"HIWORD",6)!=0)
tmp=Regs[REG_DX];
}
if (!NotUsed[REG_DX] && NotUsed[REG_AX])
{
CheckAndDeletePending(Regs[REG_AX]);
tmp+=Regs[REG_AX];
}
tmp += ";";
sprintf(LineBuffer,"%s",(char *)tmp);
}
else*/
{
GetLabel(inst.Data11,tmp);
sprintf(LineBuffer,"goto %s;",(char *)tmp);
}
CheckAndOutput(LineBuffer,How,sList);
break;
// JA, JAE, JB, JBE, JZ, JNZ, JG, JGE, JL, JLE
// Others normally do not occur in C Programs. Hence ignored.
case JA : case JAE : case JB : case JBE :
i=1; goto comjmp;
case JL : case JG : case JZ :
case JLE: case JGE: case JNZ:
i=0;
comjmp:
// No CMP instruction encountered before?
if (((char *)CompareVar.Operand1)[0]==0)
{
//printf("\nUnknown Code Structure at %X\n",InstAddr);
break;
}
sprintf(LineBuffer,"if(");
//if (i) sprintf(EndOf(LineBuffer),"(unsigned)");
sprintf(EndOf(LineBuffer),"(%s)",\
(char *)CompareVar.Operand1);
sprintf(EndOf(LineBuffer)," %s ",\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -