⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcwiz2.cpp

📁 Decompilation Dos Program is a technique that allows you to recover lost source code. It is also nee
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//	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 + -