📄 tcwiz0.cpp
字号:
[ ProcBegin - Beginning of the procedure. ]
[ Recurse - 1 if we can recursively search all procedures for functions ]
[ called and variables used and setup all the related lists. ]
[-----------------------------------------------------------------------]
*/
void TcWizard::Pass1(Byte far *ProcBegin,int Recurse)
{
Flush();
static int SwitchFormat[]={ CMP,JA,SHL,SEGMENT,JMP };
Byte far *Inst;
Disasm d;
d.SetCodePtr(CodePtr);
Dword ProcSize;
Dword ctr = SkipProcInit(ProcBegin,ProcSize);
// This initialization of ProcEndAddress is a must, in pass1.
// this prevents from tracing instructions after the end of the
// given procedure.
ProcEndAddress = ProcBegin + ctr + ProcSize;
Inst = ProcBegin + ctr;
Byte far *tInstBegin = Inst;
int NumBlocksFound=0;
if (BlockTable) free(BlockTable);
Byte far **ProcTable=NULL;
char *ProcNames;
int *ProcPercent;
int NumProcsCalled;
ComForFindAndStore:
ctr=0;
NumBlocks = 0;
NumProcsCalled=0;
while(ctr<ProcSize)
{
int val,i,oper;
int InstLen;
d.TraceInst(Inst,InstLen);
Inst += InstLen;
ctr += InstLen;
InstInfo inst = d.CurInst;
TranslateTrickyInsts(inst);
switch(inst.Instr)
{
// forming a list of functions called by this procedure.
case CALL: if (NumBlocksFound)
{
Word seg=FP_SEG(ProcBegin);
if (inst.operSize1) seg=inst.Data12;
Byte far *p=(Byte far *)MK_FP(seg,inst.Data11);
Variable v;
v.Operand=IMMEDIATE;
v.Data1=FP_OFF(p);
v.Data2=FP_SEG(p);
// if the procedure has already been scanned, skip it.
if (GlobalVars.IsPresent(v)) break;
// Check if an entry has already been made
for(int i=0;i<NumProcsCalled;i++)
if (ProcTable[i]==p) break;
// no?
if (i==NumProcsCalled)
{
ProcTable[NumProcsCalled++]=p;
}
}
else NumProcsCalled++;
break;
// checking for the Ordered-Switch.
case CMP : Byte far *tInst = Inst; int tInstLen;
for(int i=1;i<5;i++)
{
d.TraceInst(tInst,tInstLen);
if (d.CurInst.Instr!=SwitchFormat[i]) break;
tInst+=tInstLen;
}
if (i==5)
{
if (NumBlocksFound)
{
BlockTable[NumBlocks].Type = C_SWITCH_ORDERED;
BlockTable[NumBlocks].Address = FP_OFF(Inst-InstLen);
}
NumBlocks++;
}
break;
case RET : ctr = ProcSize; break;
// Loop means that we got the address of a SWITCH statement.
case LOOP:if (NumBlocksFound)
{
BlockTable[NumBlocks].Type = C_SWITCH;
BlockTable[NumBlocks].Address = inst.Data11;
}
NumBlocks++;
break;
// JA, JAE, JB, JBE, JZ, JNZ, JG, JGE, JL, JLE
// Others normally do not occur in C Programs. Hence ignored.
case JMP :
if (inst.Operand1!=IMMEDIATE) break;
case JA : case JAE : case JB : case JBE :
case JL : case JG : case JZ :
case JLE: case JGE : case JNZ:
if (NumBlocksFound)
{
// Check if the address is already present in the table.
for(register int i=0;i<NumBlocks;i++)
if (BlockTable[i].Type==C_GOTO && \
BlockTable[i].Address==inst.Data11) break;
// If not, store it.
if (i<=NumBlocks)
{
BlockTable[NumBlocks].Type = C_GOTO;
BlockTable[NumBlocks].Address = inst.Data11;
NumBlocks++;
}
}
else NumBlocks++;
break;
}
}
if (!NumBlocksFound)
{
if (NumBlocks)
{
BlockTable = (CBlock *)malloc(sizeof(CBlock)*NumBlocks);
if (!BlockTable)
{
ErrorList.Add("Not enough memory in Pass1!");
exit(1);
}
NumBlocksFound=1;
}
if (NumProcsCalled)
{
ProcTable = (Byte far **)malloc(
sizeof(Byte far *)*NumProcsCalled +
sizeof(int)*NumProcsCalled +
sizeof(char)*64*NumProcsCalled);
if (!ProcTable)
{
ErrorList.Add("Not enough memory in Pass1!");
exit(1);
}
ProcPercent=(int *)(ProcTable+NumProcsCalled);
ProcNames=(char *)(ProcPercent+NumProcsCalled);
NumBlocksFound=1;
}
if (NumBlocksFound)
{
Inst=tInstBegin;
goto ComForFindAndStore;
}
}
qsort(BlockTable,NumBlocks,sizeof(CBlock),sortFunc);
// Now find the library functions.
TLibWizard tlw;
if (tlw.CheckInLibrary("cs.lib",NumProcsCalled,ProcTable,ProcNames,ProcPercent)==0)
{
Variable v;
for(int i=0;i<NumProcsCalled;i++)
{
v.Operand=IMMEDIATE;
v.Data1=FP_OFF(ProcTable[i]);
v.Data2=FP_SEG(ProcTable[i]);
if (ProcPercent[i]>950)
GlobalVars.Add(v,VAR_LIB_FUNCTION,0,ProcNames+i*64);
else
{
GlobalVars.Add(v,VAR_USER_FUNCTION,0,NULL);
sprintf(errorStr,"Function at address %Fp not found in library",ProcTable[i]);
ErrorList.Add(errorStr);
if (Recurse) Pass1(ProcTable[i],Recurse);
}
}
}
if (ProcTable) free(ProcTable);
// Go thro' the procedure once and register all variables whose datatypes
// can be found from the code structure.
// ** Do it only if we aren't going recursively. If so, the caller will
// ** do this checking.
TranslateBlock(tInstBegin,ProcSize,SEPARATE_LINES,NULL);
}
void TcWizard::Output(const char *Statement, int How, StringList *sList)
{
String tmp,tmp1,tmp2;
if (TracingFunctionCall) How=COMMA_EXPRESSIONS;
Word iAddr;
while(FlushPending(tmp2,iAddr))
{
switch(How)
{
case SEPARATE_LINES :
tmp = tmp2+";";
if (sList) sList->Add(tmp,iAddr);
break;
case COMMA_EXPRESSIONS : tmp1 += tmp2; tmp1 += ","; break;
}
}
if (Statement) // Pass NULL to do only Flushing of pending
{ // lines.
switch(How)
{
case SEPARATE_LINES :
tmp = "";
tmp += Statement;
if (sList) sList->Add(tmp,InstAddr); break;
case COMMA_EXPRESSIONS : tmp1 += Statement;
char *ptr = (char *)tmp1;
int len = strlen(ptr);
if (ptr[len]==';') ptr[len]=',';
else tmp1 += ",";
break;
}
}
if (How==COMMA_EXPRESSIONS)
{
if (TracingFunctionCall)
{
int i=StackTop;
if (((char *)Stack[i])[0] == 0) Stack[i] = "(";
Stack[i] += tmp1;
}
else
{
if (sList) sList->Add(tmp1);
}
}
}
void TcWizard::DisplayProc(Byte far *ProcBegin)
{
StringList sList;
Dword ProcSize;
Dword ctr = SkipProcInit(ProcBegin,ProcSize);
InstAddr=FP_OFF(ProcBegin+ctr);
Variable v;
v.Operand=IMMEDIATE;
v.Data1=FP_OFF(ProcBegin);
v.Data2=FP_SEG(ProcBegin);
char FuncName[35];
if (FuncName) strcpy(FuncName,GlobalVars.GetName(v));
else strcpy(FuncName,(char *)String((Word)v.Data1));
strcat(FuncName,"()");
Output(FuncName,SEPARATE_LINES,&sList);
Output("{",SEPARATE_LINES,&sList);
// this initialization is a must in displayproc and pass1
ProcEndAddress=ProcBegin+ctr+ProcSize;
TranslateBlock(ProcBegin+ctr,ProcSize,SEPARATE_LINES,&sList);
Output("}",SEPARATE_LINES,&sList);
CBeautifier cb;
printf("\nRestructure code(Y/N)?\n");
int i=getch();
if (i=='y' || i=='Y') cb.BeautifyCode(&sList);
FILE *fp=fopen("_disc.c","a");
if (!fp) fp=fopen("_disc.c","w");
if (!fp) printf("Unable to open _disc.c\n");
else
{
cb.DisplayList(&sList,fp);
printf("Written to file.\n");
fclose(fp);
}
}
/*
[-----------------------------------------------------------------------]
[ CheckForTernaryOperCode - must be called only by TranslateBlock. ]
[-----------------------------------------------------------------------]
[ Logic: Ternary operator compiles as ]
[ CMP val1,val2 ]
[ [--- Jxx label1 ]
[ | ... ]
[ |[-- JMP label2 ]
[ [-- label1: ]
[ | ... ]
[ [- label2: ]
[ possible assignment code etc. ]
[ ##End of ternary operator code. ]
[ Find the 1st JMP from CMP, find the address given in the JMP(this is]
[ the end of the block). ]
[ Find if any registers are modified and not used in the block ]
[ (possibly used after the block(i.e. are you using the result of ]
[ the ternary operator). If so, then 'tis a ternary operator. ]
[ Code - points to the instruction after the Jxx to be checked. ]
[ ConditionStr - points to the condition eg. (i==1) ]
[-----------------------------------------------------------------------]
*/
Byte far *TcWizard::CheckForTernaryOperCode(Byte far *Code,char *ConditionStr)
{
Disasm d;
d.SetCodePtr(CodePtr);
Byte far *Inst = Code;
int InstLen;
// Find the JMP and the end of the block from that instruction.
// If we have another ternary operator inside this block, we must skip
// the JMP of the second block, so that we find the JMP of this first
// ternary operator correctly.
int NumJumpsToSkip=0;
Byte far *Fragment1Begin=0; Word Fragment1Size=0;
Byte far *Fragment2Begin=0; Word Fragment2Size=0;
Word ctr=0,BlockSize=CompareVar.EndAddress-FP_OFF(Code);
while(ctr<BlockSize)
{
d.TraceInst(Inst,InstLen);
if (d.CurInst.Instr==JMP)
{
if (!NumJumpsToSkip)
{
// Now Inst points to the JMP instruction.
Fragment1Begin = Code;
Fragment2Begin = Inst+InstLen;
Byte far *Fragment2End = (Byte far *)MK_FP(d.CurInst.Data21,d.CurInst.Data11);
Fragment1Size = Inst - Fragment1Begin;
Fragment2Size = Fragment2End - Fragment2Begin;
break;
}
else NumJumpsToSkip--;
}
else if (d.CurInst.Instr==CMP) NumJumpsToSkip++;
Inst += InstLen;
ctr += InstLen;
}
// Error in searching for the JMP?
if (ctr==BlockSize) return Code;
if (Fragment1Size<=0 || Fragment2Size<=0) return Code;
int i;
// Now find which registers are modified in the first code fragment.
Byte RegModified[8+8]; // No SegmentRegisters are checked here.
Byte RegUsed[8+8];
Byte RegModifiedLater[8+8];
Byte RegUsedLater[8+8];
for(i=0;i<16;i++)
{
RegModified[i]=0; RegUsed[i]=0;
RegModifiedLater[i]=0; RegUsedLater[i]=0;
}
TcWizardState CurState;
SaveState(CurState);
FindRegsUsed(Fragment1Begin,Fragment1Size,RegModified,RegUsed);
RestoreState(CurState);
FindRegsUsed(Fragment2Begin+Fragment2Size,15,RegModifiedLater,RegUsedLater);
RestoreState(CurState);
// Check if any of the registers were modified, but not used later.
// *** Check if RegModified[i]==1, since RegModified[i]==2 if there
// *** was a function call, whose return value type is not known.
// *** Ignore such Modifications to the register values here.
for(i=0;i<16;i++)
if ((RegModified[i]==1 && !RegUsed[i]) &&
(RegModifiedLater[i]!=1 && RegUsedLater[i]))
break;
// No such registers? Well, then this is not a ternary operator code.
if (i==16) return Code;
String t; t=ConditionStr;
String tRegs[16];
// Giving SEPARATE_LINES or COMMA_EXPRESSIONS here doesn't matter, because
// sList = NULL here.
TranslateBlock(Fragment2Begin,Fragment2Size,SEPARATE_LINES,NULL);
for(i=0;i<16;i++) tRegs[i] = t + " ? (" + Regs[i] + ") : (";
RestoreState(CurState);
TranslateBlock(Fragment1Begin,Fragment1Size,SEPARATE_LINES,NULL);
// Now change only those registers used in the ternary operator code.
for(i=0;i<16;i++)
if ((RegModified[i]==1 && !RegUsed[i]) &&
(RegModifiedLater[i]!=1 && RegUsedLater[i]))
tRegs[i] += Regs[i] + ")";
RestoreState(CurState);
for(i=0;i<16;i++)
if ((RegModified[i]==1 && !RegUsed[i]) &&
(RegModifiedLater[i]!=1 && RegUsedLater[i]))
{
// support for long-int returning ternary operators.
if (i==REG_DX || i==REG_CX) Regs[i]="HIWORD("; else Regs[i]="";
Regs[i] += tRegs[i];
if (i==REG_DX || i==REG_CX) Regs[i]+=")";
}
DestroyState(CurState);
return Fragment2Begin+Fragment2Size;
}
int TcWizard::IsEqualClosingParentheses(String &t)
{
char *ptr = (char *)t;
int OpeningParentheses=0,ClosingParentheses=0;
while(*ptr)
{
if (*ptr=='(') OpeningParentheses++;
else if (*ptr==')') ClosingParentheses++;
ptr++;
}
return (OpeningParentheses==ClosingParentheses);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -