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

📄 tcwiz1.cpp

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

/*----------------------------------------------------------------------
FillSwitchInfo - Only to fill the info into the structure passed.
----------------------------------------------------------------------*/
void TcWizard::FillSwitchInfo(Byte far *Inst,InstInfo &inst,SwitchInfo &SwInfo)
{
  int SwitchType = IsSwitchStatement(FP_OFF(Inst));
  InstInfo tinst;
  if (SwitchType==C_SWITCH)
  {
    // An ordinary switch is coded like given below.
    // MOV CX,NumClauses
    // MOV BX,SwitchTable
    // CS:
    // MOV AX,[BX]
    // CMP AX,...
    // ...
    // LOOP label
    // JMP AddressOfDefault.
    // so, to find the address of the switch table, use BX
    //     to find the address of the no. of switch clauses, use CX.
    SwInfo.NumClauses = Regs[REG_CX].ValueFromHex();
    Word Segment = FP_SEG(Inst);	// CS
    SwInfo.SwitchTable= (Byte far *)MK_FP(Segment,Regs[REG_BX].ValueFromHex());

    FindInstruction(Inst,JMP,&tinst);
    SwInfo.DefaultAddress = tinst.Data11;
    SwInfo.DeleteAfterUse=0;
  }
  else if (SwitchType==C_SWITCH_ORDERED)
  {
    // An ordered switch is coded like given below.
    // MOV Reg,val
    // CMP Reg,MAXVAL    where MAXVAL gives the count of the 'case' statements.
    // JA  AddressOfDefault
    // SHL Reg,1
    // CS:
    // JMP [Reg+AddressOfSwitchTable]
    // Now we are in the "CMP Reg,MAXVAL" instruction.
    SwInfo.NumClauses = inst.Data21+1;
    Disasm d; d.SetCodePtr(CodePtr);
    int InstLen;
    d.TraceInst(Inst,InstLen); Inst+= InstLen;	// Skip the CMP instruction.
    d.TraceInst(Inst,InstLen); Inst+= InstLen;  // Trace the JA instruction.
    SwInfo.DefaultAddress = d.CurInst.Data11;
    d.TraceInst(Inst,InstLen); Inst+= InstLen;	// Ignore the next SHL & CS:
    d.TraceInst(Inst,InstLen); Inst+= InstLen;  //  instructions.
    Word Segment = FP_SEG(Inst);	// CS

    d.TraceInst(Inst,InstLen);
    Word far *Addrs = (Word far *)MK_FP(Segment,d.CurInst.Data12);
    int *tab = new int[(SwInfo.NumClauses+1)*2];
    assert(tab!=NULL);
    for(int i=0;i<SwInfo.NumClauses;i++) tab[i] = i;
    for(int j=0;i<2*SwInfo.NumClauses;i++,j++) tab[i] = Addrs[j];
    SwInfo.SwitchTable= (Byte far *)tab;
    // Memory allocated here is to be freed by 'DecodeSwitchStatement' fn.
    SwInfo.DeleteAfterUse=1;
  }
}

/*----------------------------------------------------------------------
FindInstruction - finds the next matching instructin and stores it
in the InstInfo passed.
Also returns the address of the instruction.
----------------------------------------------------------------------*/
Byte far *TcWizard::FindInstruction(Byte far *Inst,Byte Instruc,InstInfo *inst,int *LenPtr)
{
  Disasm d;
  d.SetCodePtr(CodePtr);
  int InstLen=0;
  do
  {
    Inst += InstLen;
    d.TraceInst(Inst,InstLen);
  }while(d.CurInst.Instr != Instruc);
  *inst = d.CurInst;
  if (LenPtr) *LenPtr = InstLen;
  return Inst;
}
/*----------------------------------------------------------------------
DecodeSwitchStatement - Decodes the switch statement and prints it into
the string list passed.
----------------------------------------------------------------------*/
Byte far *TcWizard::DecodeSwitchStatement(SwitchInfo &SwInfo,int How,StringList *sList,Word BlockEndAddress)
{
  int i;
  String s_LineBuffer;
  char *LineBuffer = (char *)s_LineBuffer;
  InstInfo inst;
  Dword BlockSize;
  Byte far *Inst;
  // How to find the end of the switch statement? Here we check for the
  //  addresses given in the JMPs at the end of each CASE block, and find
  //  the address which is nearest and after the address of DEFAULT stat.
  //  (Confusing? Think for some time. 'tis a weird logic, but works here.)
  Word EndOfSwitch = 0xffff;
  Word *SwitchAddrs = (Word *)new Word[SwInfo.NumClauses+1];
  assert(SwitchAddrs);
  for(i=0;i<SwInfo.NumClauses;i++)
  {
    // 2 - denotes the sizeof(int). Only integers can be used in SWITCH.
    Word addr = *(Word far *)(SwInfo.SwitchTable+i*2+SwInfo.NumClauses*2);
    for(int j=0;j<i;j++)
      if (addr<SwitchAddrs[j]) break;
    for(int k=SwInfo.NumClauses;k>j;k--) SwitchAddrs[k] = SwitchAddrs[k-1];
    SwitchAddrs[j] = addr;

    Inst = (Byte far *)MK_FP(FP_SEG(CodePtr),addr);
    BlockSize = FindInstruction(Inst,JMP,&inst) - Inst;
    if (inst.Data11>=SwInfo.DefaultAddress && inst.Data11<EndOfSwitch)
      EndOfSwitch = inst.Data11;
  }
  if (EndOfSwitch>BlockEndAddress) EndOfSwitch=BlockEndAddress;

  SwitchAddrs[SwInfo.NumClauses] = SwInfo.DefaultAddress;
  // Now we have the EndOfSwitch address in out hands.
  Disasm d;
  d.SetCodePtr(CodePtr);
  for(i=0;i<SwInfo.NumClauses;i++)
  {
    Word addr = SwitchAddrs[i];
    Word far *AddrTable = ((Word far *)SwInfo.SwitchTable)+SwInfo.NumClauses;
    for(int j=0;j<SwInfo.NumClauses;j++)
      if (AddrTable[j]==addr) break;
    // 2 - denotes the sizeof(int). Only integers can be used in SWITCH.
    sprintf(LineBuffer,"case %d :",(int)*((Word far *)(SwInfo.SwitchTable+j*2)));
    InstAddr=addr;
    Output(LineBuffer,How,sList);
    Inst = (Byte far *)MK_FP(FP_SEG(CodePtr),addr);
    BlockSize = SwitchAddrs[i+1]-SwitchAddrs[i];
    int InstLen;
    d.TraceInst(Inst+BlockSize-2,InstLen);	//2=sizeof(JMP short_address)
    int BreakPresent=0;
    // If a BREAK is present in the block, we shall give it here, but if
    //  it is terminated by a GOTO to another place, include it in the
    //  block to be translated.
    if (d.CurInst.Instr==JMP && d.CurInst.Data11==EndOfSwitch)
    {
      BreakPresent=1;
      BlockSize -= InstLen;
    }
    int tStackTop = StackTop;
    TranslateBlock(Inst,BlockSize,How,sList);
    StackTop = tStackTop; Stack[StackTop]="";
    if (BreakPresent) Output("break;",How,sList);
    // How to find the end of the switch statement? Here we check for the
    //  addresses given in the JMPs at the end of each CASE block, and find
    //  the address which is nearest and after the address of DEFAULT stat.
    //  (Confusing? Think for some time. 'tis a weird logic, but works here.)
    if (inst.Data11>SwInfo.DefaultAddress && inst.Data11<EndOfSwitch)
      EndOfSwitch = inst.Data11;
  }
  InstAddr=SwInfo.DefaultAddress;
  Output("default :",How,sList);
  Inst = (Byte far *)MK_FP(FP_SEG(CodePtr),SwInfo.DefaultAddress);
  BlockSize = EndOfSwitch - SwInfo.DefaultAddress;
  TranslateBlock(Inst,BlockSize,How,sList);
  // inst contains the final JMP to outside the switch statement.
  Inst = (Byte far *)MK_FP(FP_SEG(CodePtr),EndOfSwitch);
  delete[] SwitchAddrs;

  if (SwInfo.DeleteAfterUse)
  {
    delete[] ((void *)SwInfo.SwitchTable);
    SwInfo.SwitchTable=NULL;
  }
  return Inst;
}
/*----------------------------------------------------------------------
GetReg - called to get the string containing the register's contents.
  This function checks if the string is empty and gives an error if so.
-----------------------------------------------------------------------*/
String &TcWizard::GetReg(int whichReg)
{
  if (Regs[whichReg].IsEmpty())
  {
    sprintf(errorStr,"Contents of empty register being accessed at %X",InstAddr);
    ErrorList.Add(errorStr);
  }
  return Regs[whichReg];
}
/*
[-----------------------------------------------------------------------]
[ GetLabel - returns 1 if the Address passed corresponds to a label	]
[  and also stores the label name in the string passed.			]
[-----------------------------------------------------------------------]
*/
int TcWizard::GetLabel(Word Address,String &s)
{
  register int i,labelcount;
  ((char *)s)[0]=0;
//  bsearch(&Address,LabelTable,NumLabels,sizeof(Word),sortFunc);
  for(i=0,labelcount=1;i<NumBlocks;i++)
  {
    if (BlockTable[i].Type==C_GOTO)
    {
      labelcount++;
      if (BlockTable[i].Address==Address)
      {
	s = "Label";
	s += labelcount;
	return 1;
      }
    }
  }
  return 0;
}
/*----------------------------------------------------------------------
	Procedures for supporting the long-int datatype are below.
----------------------------------------------------------------------*/
/*----------------------------------------------------------------------
IsLongInt - returns 1 if the address given is part of any known long-int.
Uses the GlobalVars & LocalVars variable-lists.
----------------------------------------------------------------------*/
int TcWizard::IsLongInt(Variable &v1)
{
  Variable v2; int v2Type;
  // Is it part of any known variable?
  if (LocalVars.PartOfAnyVariable(v1,v2,v2Type) ||
      GlobalVars.PartOfAnyVariable(v1,v2,v2Type))
    return (v2Type==VAR_LONG);
  return 0;
}
/*----------------------------------------------------------------------
FirstWordOfLongInt - returns 1 if the address given is the 1st word of
 any known long-int.  Uses the GlobalVars & LocalVars variable-lists.
----------------------------------------------------------------------*/
int TcWizard::IsFirstWordOfLongInt(Variable &v1)
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -