📄 disasm.cpp
字号:
// Free Disassembler and Assembler -- Disassembler
//
// Copyright (C) 2001 Oleh Yuschuk
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define STRICT
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
//#include <dir.h>
#include <math.h>
#include <float.h>
#pragma hdrstop
#pragma warning(disable:4996)//关闭旧函数声明警告
#include "disasm.h"
//bughoho. 文件扩展名改为cpp.把外部扩展变量在cpp中添加声明
int ideal; // Force IDEAL decoding mode
int lowercase; // Force lowercase display
int tabarguments; // Tab between mnemonic and arguments
int extraspace; // Extra space between arguments
int putdefseg; // Display default segments in listing
int showmemsize; // Always show memory size
int shownear; // Show NEAR modifiers
int shortstringcmds; // Use short form of string commands
int sizesens; // How to decode size-sensitive mnemonics
int symbolic; // Show symbolic addresses in disasm
int farcalls; // Accept far calls, returns & addresses
int decodevxd; // Decode VxD calls (Win95/98)
int privileged; // Accept privileged commands
int iocommand; // Accept I/O commands
int badshift; // Accept shift out of range 1..31
int extraprefix; // Accept superfluous prefixes
int lockedbus; // Accept LOCK prefixes
int stackalign; // Accept unaligned stack operations
int iswindowsnt; // When checking for dangers, assume NT
////////////////////////////////////////////////////////////////////////////////
//////////////////////////// DISASSEMBLER FUNCTIONS ////////////////////////////
// Work variables of disassembler
static ulong datasize; // Size of data (1,2,4 bytes)
static ulong addrsize; // Size of address (2 or 4 bytes)
static int segprefix; // Segment override prefix or SEG_UNDEF
static int hasrm; // Command has ModR/M byte
static int hassib; // Command has SIB byte
static int dispsize; // Size of displacement (if any)
static int immsize; // Size of immediate data (if any)
static int softerror; // Noncritical disassembler error
static int ndump; // Current length of command dump
static int nresult; // Current length of disassembly
static int addcomment; // Comment value of operand
// Copy of input parameters of function Disasm()
static char *cmd; // Pointer to binary data
static char *pfixup; // Pointer to possible fixups or NULL
static ulong size; // Remaining size of the command buffer
static t_disasm *da; // Pointer to disassembly results
static int mode; // Disassembly mode (DISASM_xxx)
// Disassemble name of 1, 2 or 4-byte general-purpose integer register and, if
// requested and available, dump its contents. Parameter type changes decoding
// of contents for some operand types.
//static void DecodeRG(int index,int datasize,int type)
//bughoho void 改为 int 返回解码得到的寄存器索引
static int DecodeRG(int index,int datasize,int type)
{
int sizeindex;
char name[9];
if (mode<DISASM_DATA)
return -1; // No need to decode
sprintf_s(da->vm_name,"%s_REG%02d",da->vm_name,datasize*8);
da->optype[stoperand] = Reg;
index&=0x07;//得到寄存器索引
if (datasize==1)
sizeindex=0;
else if (datasize==2)
sizeindex=1;
else if (datasize==4)
sizeindex=2;
else
{
da->error=DAE_INTERN;
return -1;
}
if (mode>=DISASM_FILE)
{
strcpy(name,regname[sizeindex][index]);
if (lowercase)
strlwr(name);
if (type<PSEUDOOP) // Not a pseudooperand
nresult+=sprintf(da->result+nresult,"%s",name);
//bughoho
if( sizeindex == 0 && ( index > 3 && index < 7 ) )
{
//为高位
da->highbit[stoperand] = true;
}
}
da->reg[stoperand] = index;
return index;
}
// Disassemble name of 80-bit floating-point register and, if available, dump
// its contents.
static void DecodeST(int index,int pseudoop)
{
int i;
char s[32];
if (mode<DISASM_FILE)
return; // No need to decode
index&=0x07;
i=sprintf(s,"%s(%i)",(lowercase?"st":"ST"),index);
if (pseudoop==0)
{
strcpy(da->result+nresult,s);
nresult+=i;
}
}
// Disassemble name of 64-bit MMX register.
static void DecodeMX(int index)
{
char *pr;
if (mode<DISASM_FILE)
return; // No need to decode
index&=0x07;
pr=da->result+nresult;
nresult+=sprintf(pr,"%s%i",(lowercase?"mm":"MM"),index);
}
// Disassemble name of 64-bit 3DNow! register and, if available, dump its
// contents.
static void DecodeNR(int index)
{
char *pr;
if (mode<DISASM_FILE)
return; // No need to decode
index&=0x07;
pr=da->result+nresult;
nresult+=sprintf(pr,"%s%i",(lowercase?"mm":"MM"),index);
};
// Service function, adds valid memory adress in MASM or Ideal format to
// disassembled string. Parameters: defseg - default segment for given
// register combination, descr - fully decoded register part of address,
// offset - constant part of address, dsize - data size in bytes. If global
// flag 'symbolic' is set, function also tries to decode offset as name of
// some label.
static void Memadr(int defseg,const char *descr,long offset,int dsize)
{
int i,n,seg;
char *pr;
char s[TEXTLEN];
if (mode<DISASM_FILE || descr==NULL)
return; // No need or possibility to decode
char segstr[32] = {0};
if( da->segment != SEG_UNDEF )
{
if( da->segment == SEG_FS )
strcpy(segstr,"FS");
else if( da->segment != SEG_UNDEF && da->segment == SEG_GS )
strcpy(segstr,"GS");
}
sprintf_s(da->vm_name,"%s_%sMEM%02d",da->vm_name,segstr,dsize*8);
da->optype[stoperand] = Mem;
pr=da->result+nresult; n=0;
if (segprefix!=SEG_UNDEF)
seg=segprefix;
else seg=defseg;
if (ideal!=0)
pr[n++]='[';
// In some cases Disassembler may omit size of memory operand. Namely, flag
// showmemsize must be 0, type bit C_EXPL must be 0 (this bit namely means
// that explicit operand size is necessary) and type of command must not be
// C_MMX or C_NOW (because bit C_EXPL has in these cases different meaning).
// Otherwise, exact size must be supplied.
if ( showmemsize!=0 || (da->cmdtype & C_TYPEMASK)==C_MMX ||
(da->cmdtype & C_TYPEMASK)==C_NOW || (da->cmdtype & C_EXPL)!=0 )
{
if (dsize<sizeof(sizename)/sizeof(sizename[0]))
n+=sprintf(pr+n,"%s %s",sizename[dsize],(ideal==0?"PTR ":""));
else
n+=sprintf(pr+n,"(%i-BYTE) %s",dsize,(ideal==0?"PTR ":""));
}
if ((putdefseg!=0 || seg!=defseg) && seg!=SEG_UNDEF)
n += sprintf(pr+n,"%s:",segname[seg]);
if (ideal==0)
pr[n++]='[';
n += sprintf(pr+n,"%s",descr);
if (lowercase)
strlwr(pr);
if (offset==0L)
{
if (*descr=='\0') pr[n++]='0';
}
else
{
if (symbolic && mode>=DISASM_CODE)
i=Decodeaddress(offset,s,TEXTLEN-n-24,NULL);
else
i=0;
if (i>0)
{ // Offset decoded in symbolic form
if (*descr!='\0') pr[n++]='+';
strcpy(pr+n,s); n+=i;
}
else if (offset<0 && offset>-16384 && *descr!='\0')
n+=sprintf(pr+n,"-%lX",-offset);
else
{
if (*descr!='\0')
pr[n++]='+';
n+=sprintf(pr+n,"%lX",offset);
};
};
pr[n++]=']'; pr[n]='\0';
nresult+=n;
};
// Disassemble memory/register from the ModRM/SIB bytes and, if available, dump
// address and contents of memory.
static void DecodeMR(int type)
{
int j,memonly,inmemory,seg;
int c,sib;
ulong dsize,regsize,addr;
char s[TEXTLEN];
if (size<2)
{
da->error=DAE_CROSS;
return;
} // ModR/M byte outside the memory block
hasrm=1;
dsize=regsize=datasize; // Default size of addressed reg/memory
memonly=0; // Register in ModM field is allowed
// Size and kind of addressed memory or register in ModM has no influence on
// the command size, and exact calculations are omitted if only command size
// is requested. If register is used, optype will be incorrect and we need
// to correct it later.
c=cmd[1] & 0xC7; // Leave only Mod and M fields
if (mode>=DISASM_DATA)
{
if ((c & 0xC0)==0xC0) // Register operand
inmemory=0;
else // Memory operand
inmemory=1;
//判断是内存操作数还是寄存器操作数,并确定长度
switch (type)
{
case MRG: // Memory/register in ModRM byte
if (inmemory)
{
if (datasize==1)
da->memtype=DEC_BYTE;
else if (datasize==2)
da->memtype=DEC_WORD;
else
da->memtype=DEC_DWORD;
}
break;
case MRJ: // Memory/reg in ModRM as JUMP target
if (datasize!=2 && inmemory)
da->memtype=DEC_DWORD;
if (mode>=DISASM_FILE && shownear!=0)
nresult+=sprintf(da->result+nresult,"%s ",(lowercase?"near":"NEAR"));
break;
case MR1: // 1-byte memory/register in ModRM byte
dsize=regsize=1;
if (inmemory) da->memtype=DEC_BYTE;
break;
case MR2: // 2-byte memory/register in ModRM byte
dsize=regsize=2;
if (inmemory) da->memtype=DEC_WORD;
break;
case MR4: // 4-byte memory/register in ModRM byte
case RR4: // 4-byte memory/register (register only)
dsize=regsize=4;
if (inmemory) da->memtype=DEC_DWORD;
break;
case MR8: // 8-byte memory/MMX register in ModRM
case RR8: // 8-byte MMX register only in ModRM
dsize=8;
if (inmemory) da->memtype=DEC_QWORD;
break;
case MRD: // 8-byte memory/3DNow! register in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
dsize=8;
if (inmemory) da->memtype=DEC_3DNOW;
break;
case MMA: // Memory address in ModRM byte for LEA
memonly=1;
break;
case MML: // Memory in ModRM byte (for LES)
dsize=datasize+2; memonly=1;
if (datasize==4 && inmemory)
da->memtype=DEC_FWORD;
da->warnings|=DAW_SEGMENT;
break;
case MMS: // Memory in ModRM byte (as SEG:OFFS)
dsize=datasize+2; memonly=1;
if (datasize==4 && inmemory)
da->memtype=DEC_FWORD;
if (mode>=DISASM_FILE)
nresult+=sprintf(da->result+nresult,"%s ",(lowercase?"far":"FAR"));
break;
case MM6: // Memory in ModRM (6-byte descriptor)
dsize=6; memonly=1;
if (inmemory) da->memtype=DEC_FWORD;
break;
case MMB: // Two adjacent memory locations (BOUND)
dsize=(ideal?datasize:datasize*2); memonly=1;
break;
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
dsize=2; memonly=1;
if (inmemory) da->memtype=DEC_WORD;
break;
case MD4: // Memory in ModRM byte (32-bit integer)
dsize=4; memonly=1;
if (inmemory) da->memtype=DEC_DWORD;
break;
case MD8: // Memory in ModRM byte (64-bit integer)
dsize=8; memonly=1;
if (inmemory) da->memtype=DEC_QWORD;
break;
case MDA: // Memory in ModRM byte (80-bit BCD)
dsize=10; memonly=1;
if (inmemory) da->memtype=DEC_TBYTE;
break;
case MF4: // Memory in ModRM byte (32-bit float)
dsize=4; memonly=1;
if (inmemory) da->memtype=DEC_FLOAT4;
break;
case MF8: // Memory in ModRM byte (64-bit float)
dsize=8; memonly=1;
if (inmemory) da->memtype=DEC_FLOAT8;
break;
case MFA: // Memory in ModRM byte (80-bit float)
dsize=10; memonly=1;
if (inmemory) da->memtype=DEC_FLOAT10;
break;
case MFE: // Memory in ModRM byte (FPU environment)
dsize=28; memonly=1;
break;
case MFS: // Memory in ModRM byte (FPU state)
dsize=108; memonly=1;
break;
case MFX: // Memory in ModRM byte (ext. FPU state)
dsize=512; memonly=1;
break;
default: // Operand is not in ModM!
da->error=DAE_INTERN;
break;
};
};
addr=0;
// There are many possibilities to decode ModM/SIB address. The first
// possibility is register in ModM - general-purpose, MMX or 3DNow!
//为0xC0时则是寄存器
if ((c & 0xC0)==0xC0)
{ // Decode register operand
if (type==MR8 || type==RR8)
DecodeMX(c); // MMX register
else if (type==MRD || type==RRD)
DecodeNR(c); // 3DNow! register
else
{
DecodeRG(c,regsize,type); // General-purpose register
}
if (memonly!=0)
softerror=DAE_MEMORY; // Register where only memory allowed
return;
}
// Next possibility: 16-bit addressing mode, very seldom in 32-bit flat model
// but still supported by processor. SIB byte is never used here.
// 下一个可能: 16位地址模式.在32位平坦模式下很少见但是处理器仍然支持
if (addrsize==2)
{
if (c==0x06)
{ // Special case of immediate address
dispsize=2;
if (size<4)
da->error=DAE_CROSS; // Disp16 outside the memory block
else if (mode>=DISASM_DATA)
{
da->adrconst=addr=*(ushort *)(cmd+2);
if (addr==0) da->zeroconst=1;
seg=SEG_DS;
Memadr(seg,"",addr,dsize);
}
}
else
{
da->indexed=1;
if ((c & 0xC0)==0x40)
{ // 8-bit signed displacement
if (size<3)
da->error=DAE_CROSS;
else
addr=(signed char)cmd[2] & 0xFFFF;
dispsize=1;
}
else if ((c & 0xC0)==0x80)
{ // 16-bit unsigned displacement
if (size<4)
da->error=DAE_CROSS;
else
addr=*(ushort *)(cmd+2);
dispsize=2;
}
if (mode>=DISASM_DATA && da->error==DAE_NOERR)
{
da->adrconst=addr;
if (addr==0)
da->zeroconst=1;
seg=addr16[c & 0x07].defseg;
Memadr(seg,addr16[c & 0x07].descr,addr,dsize);
}
}
}
// Next possibility: immediate 32-bit address.
// 下一个可能 : 32位立即数的内存地址
else if (c==0x05)
{ // Special case of immediate address
dispsize=4;
if (size<6)
da->error=DAE_CROSS; // Disp32 outside the memory block
else if (mode>=DISASM_DATA)
{
da->adrconst=addr=*(ulong *)(cmd+2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -