mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
a36121fe92
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@109 21ef857c-d57f-4fe0-8362-d861dc6d29cd
1974 lines
65 KiB
C#
1974 lines
65 KiB
C#
/* Original file: disasm.c
|
|
*
|
|
* Free Disassembler and Assembler -- Disassembler
|
|
*
|
|
* Copyright (C) 2008 wj32
|
|
* 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
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
|
|
namespace ProcessHacker
|
|
{
|
|
public unsafe partial class Asm
|
|
{
|
|
public class Disassembler
|
|
{
|
|
private int _dataSize;
|
|
private int _addrSize;
|
|
private int _segPrefix;
|
|
private bool _hasRM;
|
|
private bool _hasSIB;
|
|
private int _dispSize;
|
|
private int _immSize;
|
|
private int _softError;
|
|
private bool _addComment;
|
|
|
|
private byte* _cmd;
|
|
private byte* _pFixup;
|
|
private int _size;
|
|
private Disasm _da;
|
|
private int _mode;
|
|
|
|
private void DecodeRG(int index, int dataSize, int type)
|
|
{
|
|
int sizeIndex;
|
|
string name = "";
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
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;
|
|
}
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
name = RegName[sizeIndex][index];
|
|
|
|
if (Lowercase)
|
|
name = name.ToLower();
|
|
if (type < PseudoOp)
|
|
_da.Result.Append(name);
|
|
}
|
|
}
|
|
|
|
private void DecodeST(int index, int pseudoOp)
|
|
{
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
index &= 0x07;
|
|
|
|
if (pseudoOp == 0)
|
|
{
|
|
_da.Result.Append(string.Format("{0}({1})", Lowercase ? "st" : "ST", index));
|
|
}
|
|
}
|
|
|
|
private void DecodeMX(int index)
|
|
{
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
index &= 0x07;
|
|
|
|
_da.Result.Append(string.Format("{0}{1}", Lowercase ? "mm" : "MM", index));
|
|
}
|
|
|
|
private void DecodeNR(int index)
|
|
{
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
index &= 0x07;
|
|
|
|
_da.Result.Append(string.Format("{0}{1}", Lowercase ? "mm" : "MM", index));
|
|
}
|
|
|
|
private string DecodeAddress(int addr, out string comment)
|
|
{
|
|
comment = "";
|
|
|
|
return "0x" + addr.ToString("x8");
|
|
}
|
|
|
|
private void MemAdr(int defSeg, string descr, int offset, int dsize)
|
|
{
|
|
int seg, i;
|
|
string pr = "";
|
|
string s = "";
|
|
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
if (_segPrefix != SEG_UNDEF)
|
|
seg = _segPrefix;
|
|
else
|
|
seg = defSeg;
|
|
|
|
if (Ideal)
|
|
pr += "[";
|
|
|
|
if (ShowMemSize != 0 ||
|
|
(_da.CmdType & C_TYPEMASK) == C_MMX ||
|
|
(_da.CmdType & C_TYPEMASK) == C_NOW ||
|
|
(_da.CmdType & C_EXPL) != 0)
|
|
{
|
|
if (dsize < SizeName.Length)
|
|
pr += string.Format("{0} {1}", SizeName[dsize], (!Ideal ? "PTR " : ""));
|
|
else
|
|
pr += string.Format("({0}-BYTE) {1}", dsize, (!Ideal ? "PTR " : ""));
|
|
}
|
|
|
|
if ((PutDefSeg != 0 || seg != defSeg) && seg != SEG_UNDEF)
|
|
pr += SegName[seg] + ":";
|
|
|
|
if (!Ideal)
|
|
pr += "[";
|
|
|
|
pr += descr;
|
|
|
|
if (Lowercase)
|
|
pr = pr.ToLower();
|
|
|
|
if (offset == 0)
|
|
{
|
|
if (descr == "")
|
|
pr += "0";
|
|
}
|
|
else
|
|
{
|
|
if (Symbolic && _mode >= DISASM_CODE)
|
|
{
|
|
string t;
|
|
|
|
s = DecodeAddress(offset, out t);
|
|
i = 1;
|
|
}
|
|
else
|
|
i = 0;
|
|
|
|
if (i > 0)
|
|
{
|
|
if (descr != "")
|
|
pr += "+";
|
|
|
|
pr += s;
|
|
}
|
|
else if (offset < 0 && offset > -16384 && descr != "")
|
|
pr += string.Format("-{0:X}", -offset);
|
|
else
|
|
{
|
|
if (descr != "")
|
|
pr += "+";
|
|
|
|
pr += string.Format("{0:X}", offset);
|
|
}
|
|
}
|
|
|
|
pr += "]";
|
|
|
|
_da.Result.Append(pr);
|
|
}
|
|
|
|
private void DecodeMR(int type)
|
|
{
|
|
bool inmemory, memonly;
|
|
int j;
|
|
int seg = 0;
|
|
int c, sib;
|
|
int dsize, regsize, addr;
|
|
string s = "";
|
|
|
|
if (_size < 2)
|
|
{
|
|
_da.Error = DAE_CROSS;
|
|
return;
|
|
}
|
|
|
|
_hasRM = true;
|
|
dsize = regsize = _dataSize;
|
|
memonly = false;
|
|
|
|
c = _cmd[1] & 0xc7;
|
|
|
|
if (_mode >= DISASM_DATA)
|
|
{
|
|
if ((c & 0xc0) == 0xc0)
|
|
inmemory = false;
|
|
else
|
|
inmemory = true;
|
|
|
|
#region Switch
|
|
|
|
switch (type)
|
|
{
|
|
case MRG:
|
|
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:
|
|
if (_dataSize != 2 && inmemory)
|
|
_da.MemType = DEC_DWORD;
|
|
if (_mode >= DISASM_FILE && ShowNear != 0)
|
|
_da.Result.Append(Lowercase ? "near " : "NEAR ");
|
|
|
|
break;
|
|
|
|
case MR1:
|
|
dsize = regsize = 1;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_BYTE;
|
|
|
|
break;
|
|
|
|
case MR2:
|
|
dsize = regsize = 2;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_WORD;
|
|
|
|
break;
|
|
|
|
case MR4:
|
|
case RR4:
|
|
dsize = regsize = 4;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_DWORD;
|
|
|
|
break;
|
|
|
|
case MR8:
|
|
case RR8:
|
|
dsize = 8;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_QWORD;
|
|
|
|
break;
|
|
|
|
case MRD:
|
|
case RRD:
|
|
dsize = 8;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_3DNOW;
|
|
|
|
break;
|
|
|
|
case MMA:
|
|
memonly = true;
|
|
|
|
break;
|
|
|
|
case MML:
|
|
dsize = _dataSize + 2;
|
|
memonly = true;
|
|
|
|
if (_dataSize == 4 && inmemory)
|
|
_da.MemType = DEC_FWORD;
|
|
|
|
_da.Warnings |= DAW_SEGMENT;
|
|
|
|
break;
|
|
|
|
case MMS:
|
|
dsize = _dataSize + 2;
|
|
memonly = true;
|
|
|
|
if (_dataSize == 4 && inmemory)
|
|
_da.MemType = DEC_FWORD;
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Result.Append(Lowercase ? "far " : "FAR ");
|
|
|
|
break;
|
|
|
|
case MM6:
|
|
dsize = 6;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_FWORD;
|
|
|
|
break;
|
|
|
|
case MMB:
|
|
dsize = (Ideal ? _dataSize : _dataSize * 2);
|
|
memonly = true;
|
|
|
|
break;
|
|
|
|
case MD2:
|
|
case MB2:
|
|
dsize = 2;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_WORD;
|
|
|
|
break;
|
|
|
|
case MD4:
|
|
dsize = 4;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_DWORD;
|
|
|
|
break;
|
|
|
|
case MD8:
|
|
dsize = 8;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_QWORD;
|
|
|
|
break;
|
|
|
|
case MDA:
|
|
dsize = 10;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_TBYTE;
|
|
|
|
break;
|
|
|
|
case MF4:
|
|
dsize = 4;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_FLOAT4;
|
|
|
|
break;
|
|
|
|
case MF8:
|
|
dsize = 8;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_FLOAT8;
|
|
|
|
break;
|
|
|
|
case MFA:
|
|
dsize = 10;
|
|
memonly = true;
|
|
|
|
if (inmemory)
|
|
_da.MemType = DEC_FLOAT10;
|
|
|
|
break;
|
|
|
|
case MFE:
|
|
dsize = 28;
|
|
memonly = true;
|
|
|
|
break;
|
|
|
|
case MFS:
|
|
dsize = 108;
|
|
memonly = true;
|
|
|
|
break;
|
|
|
|
case MFX:
|
|
dsize = 512;
|
|
memonly = true;
|
|
|
|
break;
|
|
|
|
default:
|
|
_da.Error = DAE_INTERN;
|
|
|
|
break;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
addr = 0;
|
|
|
|
if ((c & 0xc0) == 0xc0)
|
|
{
|
|
if (type == MR8 || type == RR8)
|
|
DecodeMX(c);
|
|
else if (type == MRD || type == RRD)
|
|
DecodeNR(c);
|
|
else
|
|
DecodeRG(c, regsize, type);
|
|
|
|
if (memonly)
|
|
_softError = DAE_MEMORY;
|
|
|
|
return;
|
|
}
|
|
|
|
if (_addrSize == 2)
|
|
{
|
|
if (c == 0x06)
|
|
{
|
|
_dispSize = 2;
|
|
|
|
if (_size < 4)
|
|
_da.Error = DAE_CROSS;
|
|
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)
|
|
{
|
|
if (_size < 3)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
addr = (sbyte)_cmd[2] & 0xffff;
|
|
|
|
_dispSize = 1;
|
|
}
|
|
else if ((c & 0xc0) == 0x80)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
else if (c == 0x05)
|
|
{
|
|
_dispSize = 4;
|
|
|
|
if (_size < 6)
|
|
_da.Error = DAE_CROSS;
|
|
else if (_mode >= DISASM_DATA)
|
|
{
|
|
_da.AdrConst = addr = *(int*)(_cmd + 2);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + 2;
|
|
|
|
_da.FixupSize += 4;
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
seg = SEG_DS;
|
|
MemAdr(seg, "", addr, dsize);
|
|
}
|
|
}
|
|
else if ((c & 0x07) == 0x04)
|
|
{
|
|
sib = _cmd[2];
|
|
_hasSIB = true;
|
|
|
|
if (c == 0x04 && (sib & 0x07) == 0x05)
|
|
{
|
|
_dispSize = 4;
|
|
|
|
if (_size < 7)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
_da.AdrConst = addr = *(int*)(_cmd + 3);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + 3;
|
|
|
|
_da.FixupSize += 4;
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if ((sib & 0x38) != 0x20)
|
|
{
|
|
_da.Indexed = 1;
|
|
|
|
if (type == MRJ)
|
|
_da.JmpTable = addr;
|
|
}
|
|
seg = SEG_DS;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((c & 0xc0) == 0x40)
|
|
{
|
|
_dispSize = 1;
|
|
|
|
if (_size < 4)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
_da.AdrConst = addr = (sbyte)_cmd[3];
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
}
|
|
}
|
|
else if ((c & 0xc0) == 0x80)
|
|
{
|
|
_dispSize = 4;
|
|
|
|
if (_size < 7)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
_da.AdrConst = addr = *(int*)(_cmd + 3);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + 3;
|
|
|
|
_da.FixupSize += 4;
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (type == MRJ)
|
|
_da.JmpTable = addr;
|
|
}
|
|
}
|
|
|
|
_da.Indexed = 1;
|
|
j = sib & 0x07;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
s = RegName[2][j];
|
|
seg = Addr32[j].DefSeg;
|
|
}
|
|
}
|
|
|
|
if ((sib & 0x38) != 0x20)
|
|
{
|
|
if ((sib & 0xc0) == 0x40)
|
|
_da.Indexed = 2;
|
|
else if ((sib & 0xc0) == 0x80)
|
|
_da.Indexed = 4;
|
|
else if ((sib & 0xc0) == 0xc0)
|
|
_da.Indexed = 8;
|
|
else
|
|
_da.Indexed = 1;
|
|
}
|
|
|
|
if (_mode >= DISASM_FILE && _da.Error == DAE_NOERR)
|
|
{
|
|
if ((sib & 0x38) != 0x20)
|
|
{
|
|
if (s != "")
|
|
s += "+";
|
|
|
|
s += Addr32[(sib >> 3) & 0x07].Descr;
|
|
|
|
if ((sib & 0xc0) == 0x40)
|
|
{
|
|
_da.JmpTable = 0;
|
|
s += "*2";
|
|
}
|
|
else if ((sib & 0xc0) == 0x80)
|
|
{
|
|
s += "*4";
|
|
}
|
|
else if ((sib & 0xc0) == 0xc0)
|
|
{
|
|
_da.JmpTable = 0;
|
|
s += "*8";
|
|
}
|
|
}
|
|
|
|
MemAdr(seg, s, addr, dsize);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((c & 0xc0) == 0x40)
|
|
{
|
|
_dispSize = 1;
|
|
|
|
if (_size < 3)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
_da.AdrConst = addr = (sbyte)_cmd[2];
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
}
|
|
}
|
|
else if ((c & 0xc0) == 0x80)
|
|
{
|
|
_dispSize = 4;
|
|
|
|
if (_size < 6)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
_da.AdrConst = addr = *(int*)(_cmd + 2);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + 2;
|
|
|
|
_da.FixupSize += 4;
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (type == MRJ)
|
|
_da.JmpTable = addr;
|
|
}
|
|
}
|
|
|
|
_da.Indexed = 1;
|
|
|
|
if (_mode == DISASM_FILE && _da.Error == DAE_NOERR)
|
|
{
|
|
seg = Addr32[c & 0x07].DefSeg;
|
|
MemAdr(seg, Addr32[c & 0x07].Descr, addr, dsize);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DecodeSO()
|
|
{
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
if (_dataSize == 1)
|
|
_da.MemType = DEC_BYTE;
|
|
else if (_dataSize == 2)
|
|
_da.MemType = DEC_WORD;
|
|
else if (_dataSize == 4)
|
|
_da.MemType = DEC_DWORD;
|
|
|
|
_da.Indexed = 1;
|
|
MemAdr(SEG_DS, RegName[_addrSize == 2 ? 1 : 2][REG_ESI], 0, _dataSize);
|
|
}
|
|
|
|
private void DecodeDE()
|
|
{
|
|
int seg;
|
|
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
if (_dataSize == 1)
|
|
_da.MemType = DEC_BYTE;
|
|
else if (_dataSize == 2)
|
|
_da.MemType = DEC_WORD;
|
|
else if (_dataSize == 4)
|
|
_da.MemType = DEC_DWORD;
|
|
|
|
_da.Indexed = 1;
|
|
seg = _segPrefix;
|
|
_segPrefix = SEG_ES;
|
|
MemAdr(SEG_DS, RegName[_addrSize == 2 ? 1 : 2][REG_EDI], 0, _dataSize);
|
|
_segPrefix = seg;
|
|
}
|
|
|
|
private void DecodeXL()
|
|
{
|
|
if (_mode < DISASM_FILE)
|
|
return;
|
|
|
|
_da.MemType = DEC_BYTE;
|
|
_da.Indexed = 1;
|
|
MemAdr(SEG_DS, (_addrSize == 2 ? "BX+AL" : "EBX+AL"), 0, 1);
|
|
}
|
|
|
|
private void DecodeIM(int constSize, int sxt, int type)
|
|
{
|
|
int i;
|
|
int data;
|
|
int l;
|
|
string name = "";
|
|
string comment = "";
|
|
|
|
_immSize += constSize;
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
l = 1 + (_hasRM ? 1 : 0) + (_hasSIB ? 1 : 0) + _dispSize + (_immSize - constSize);
|
|
data = 0;
|
|
|
|
if (_size < l + constSize)
|
|
_da.Error = DAE_CROSS;
|
|
else if (constSize == 1)
|
|
{
|
|
if (sxt == 0)
|
|
data = _cmd[l];
|
|
else
|
|
data = (sbyte)_cmd[l];
|
|
|
|
if (type == IMS && ((data & 0xe0) != 0 || data == 0))
|
|
{
|
|
_da.Warnings |= DAW_SHIFT;
|
|
_da.CmdType |= C_RARE;
|
|
}
|
|
}
|
|
else if (constSize == 2)
|
|
{
|
|
if (sxt == 0)
|
|
data = *(ushort*)(_cmd + l);
|
|
else
|
|
data = *(short*)(_cmd + l);
|
|
}
|
|
else
|
|
{
|
|
data = *(int*)(_cmd + l);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + l;
|
|
|
|
_da.FixupSize += 4;
|
|
}
|
|
|
|
if (sxt == 2)
|
|
data &= 0x0000ffff;
|
|
if (data == 0 && _da.Error == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (_da.ImmConst == 0)
|
|
_da.ImmConst = data;
|
|
if (_mode >= DISASM_FILE && _da.Error == DAE_NOERR)
|
|
{
|
|
if (_mode >= DISASM_CODE && type != IMU)
|
|
{
|
|
name = DecodeAddress(data, out comment);
|
|
i = 1;
|
|
}
|
|
else
|
|
{
|
|
i = 0;
|
|
comment = "";
|
|
}
|
|
|
|
if (i != 0 && Symbolic)
|
|
_da.Result.Append(name);
|
|
else if (type == IMU || type == IMS || type == IM2 || data >= 0 || data < NegLimit)
|
|
_da.Result.Append(string.Format("{0:X}", data));
|
|
else
|
|
_da.Result.Append(string.Format("-{0:X}", -data));
|
|
|
|
if (_addComment && comment != "")
|
|
_da.Comment += comment;
|
|
}
|
|
}
|
|
|
|
private void DecodeVX()
|
|
{
|
|
int l, data;
|
|
_immSize += 4;
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
l = 1 + (_hasRM ? 1 : 0) + (_hasSIB ? 1 : 0) + _dispSize + (_immSize - 4);
|
|
|
|
if (_size < l + 4)
|
|
{
|
|
_da.Error = DAE_CROSS;
|
|
return;
|
|
}
|
|
|
|
data = *(int*)(_cmd + l);
|
|
|
|
if (data == 0 && _da.Error == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (_da.ImmConst == 0)
|
|
_da.ImmConst = data;
|
|
|
|
if (_mode >= DISASM_FILE && _da.Error == DAE_NOERR)
|
|
{
|
|
if ((data & 0x00008000) != 0 && _da.Result.ToString().StartsWith("VxDCall"))
|
|
_da.Result.Append(Lowercase ? "vxdjmp" : "VxDJump");
|
|
|
|
_da.Result.Append(string.Format("{0:X}", data));
|
|
}
|
|
}
|
|
|
|
private void DecodeC1()
|
|
{
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
_da.ImmConst = 1;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Result.Append("1");
|
|
}
|
|
|
|
private void DecodeIA()
|
|
{
|
|
int addr;
|
|
|
|
if (_size < 1 + _addrSize)
|
|
{
|
|
_da.Error = DAE_CROSS;
|
|
return;
|
|
}
|
|
|
|
_dispSize = _addrSize;
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
if (_dataSize == 1)
|
|
_da.MemType = DEC_BYTE;
|
|
else if (_dataSize == 2)
|
|
_da.MemType = DEC_WORD;
|
|
else if (_dataSize == 4)
|
|
_da.MemType = DEC_DWORD;
|
|
|
|
if (_addrSize == 2)
|
|
addr = *(ushort*)(_cmd + 1);
|
|
else
|
|
{
|
|
addr = *(int*)(_cmd + 1);
|
|
|
|
if (_pFixup == null)
|
|
_pFixup = _cmd + 1;
|
|
|
|
_da.FixupSize += 4;
|
|
}
|
|
|
|
_da.AdrConst = addr;
|
|
|
|
if (addr == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
MemAdr(SEG_DS, "", addr, _dataSize);
|
|
}
|
|
|
|
private void DecodeRJ(int offsize, int nextIp)
|
|
{
|
|
int i;
|
|
int addr;
|
|
string s = "";
|
|
|
|
if (_size < offsize + 1)
|
|
{
|
|
_da.Error = DAE_CROSS;
|
|
return;
|
|
}
|
|
|
|
_dispSize = offsize;
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
if (offsize == 1)
|
|
addr = (sbyte)_cmd[1] + nextIp;
|
|
else if (offsize == 2)
|
|
addr = *(short*)(_cmd + 1) + nextIp;
|
|
else
|
|
addr = *(int*)(_cmd + 1) + nextIp;
|
|
|
|
if (_dataSize == 2)
|
|
addr &= 0xffff;
|
|
|
|
_da.JmpConst = addr;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
if (offsize == 1)
|
|
_da.Result.Append(Lowercase ? "short " : "SHORT ");
|
|
|
|
if (_mode >= DISASM_CODE)
|
|
{
|
|
s = DecodeAddress(addr, out _da.Comment);
|
|
i = s.Length;
|
|
}
|
|
else
|
|
{
|
|
i = 0;
|
|
}
|
|
|
|
if (!Symbolic || i == 0)
|
|
_da.Result.Append(string.Format("{0:x8}", addr));
|
|
else
|
|
_da.Result.Append(s);
|
|
|
|
if (!Symbolic && i != 0 && _da.Comment != "")
|
|
_da.Comment = s;
|
|
}
|
|
}
|
|
|
|
private void DecodeJF()
|
|
{
|
|
int addr, seg;
|
|
|
|
if (_size < (1 + _addrSize + 2))
|
|
{
|
|
_da.Error = DAE_CROSS;
|
|
return;
|
|
}
|
|
|
|
_dispSize = _addrSize;
|
|
_immSize = 2;
|
|
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
if (_addrSize == 2)
|
|
{
|
|
addr = *(ushort*)(_cmd + 1);
|
|
seg = *(ushort*)(_cmd + 3);
|
|
}
|
|
else
|
|
{
|
|
addr = *(int*)(_cmd + 1);
|
|
seg = *(ushort*)(_cmd + 5);
|
|
}
|
|
|
|
_da.JmpConst = addr;
|
|
_da.ImmConst = seg;
|
|
|
|
if (addr == 0 || seg == 0)
|
|
_da.ZeroConst = 1;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
_da.Result.Append(string.Format("{0} {1:x4}:{1:x8}",
|
|
Lowercase ? "far" : "FAR", seg, addr));
|
|
}
|
|
}
|
|
|
|
private void DecodeSG(int index)
|
|
{
|
|
if (_mode < DISASM_DATA)
|
|
return;
|
|
|
|
index &= 0x07;
|
|
|
|
if (index >= 6)
|
|
_softError = DAE_BADSEG;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
_da.Result.Append(Lowercase ? SegName[index].ToLower() : SegName[index]);
|
|
}
|
|
}
|
|
|
|
private void DecodeCR(int index)
|
|
{
|
|
_hasRM = true;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
index = (index >> 3) & 0x07;
|
|
_da.Result.Append(Lowercase ? CrName[index].ToLower() : CrName[index]);
|
|
}
|
|
}
|
|
|
|
private void DecodeDR(int index)
|
|
{
|
|
_hasRM = true;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
index = (index >> 3) & 0x07;
|
|
_da.Result.Append(Lowercase ? DrName[index].ToLower() : DrName[index]);
|
|
}
|
|
}
|
|
|
|
private int Get3DNowSuffix()
|
|
{
|
|
int c, sib;
|
|
int offset;
|
|
|
|
if (_size < 3)
|
|
return -1;
|
|
|
|
offset = 3;
|
|
c = _cmd[3] & 0xc7;
|
|
|
|
if ((c & 0xc0) == 0xc0)
|
|
{ }
|
|
else if (_addrSize == 2)
|
|
{
|
|
if (c == 0x06)
|
|
offset += 2;
|
|
else if ((c & 0xc0) == 0x40)
|
|
offset++;
|
|
else if ((c & 0xc0) == 0x80)
|
|
offset += 2;
|
|
}
|
|
else if (c == 0x05)
|
|
offset += 4;
|
|
else if ((c & 0x07) == 0x04)
|
|
{
|
|
if (_size < 4)
|
|
return -1;
|
|
|
|
sib = _cmd[3];
|
|
offset++;
|
|
|
|
if (c == 0x04 && (sib & 0x07) == 0x05)
|
|
offset += 4;
|
|
else if ((c & 0xc0) == 0x40)
|
|
offset += 1;
|
|
else if ((c & 0xc0) == 0x80)
|
|
offset += 4;
|
|
}
|
|
else if ((c & 0xc0) == 0x40)
|
|
offset += 1;
|
|
else if ((c & 0xc0) == 0x80)
|
|
offset += 4;
|
|
|
|
if (offset >= _size)
|
|
return -1;
|
|
|
|
return _cmd[offset];
|
|
}
|
|
|
|
private int CheckCondition(int code, int flags)
|
|
{
|
|
int cond, temp;
|
|
|
|
switch (code & 0x0e)
|
|
{
|
|
case 0:
|
|
cond = flags & 0x0800;
|
|
break;
|
|
case 2:
|
|
cond = flags & 0x0001;
|
|
break;
|
|
case 4:
|
|
cond = flags & 0x0040;
|
|
break;
|
|
case 6:
|
|
cond = flags & 0x0041;
|
|
break;
|
|
case 8:
|
|
cond = flags & 0x0080;
|
|
break;
|
|
case 10:
|
|
cond = flags & 0x0004;
|
|
break;
|
|
case 12:
|
|
temp = flags & 0x0880;
|
|
cond = (temp == 0x0800 || temp == 0x0080) ? 1 : 0;
|
|
break;
|
|
case 14:
|
|
temp = flags & 0x0880;
|
|
cond = (temp == 0x0800 || temp == 0x0080 || (flags & 0x0040) != 0) ? 1 : 0;
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
if ((code & 0x01) == 0)
|
|
return (cond != 0) ? 1 : 0;
|
|
else
|
|
return (cond == 0) ? 1 : 0;
|
|
}
|
|
|
|
public int Disassemble(byte[] src, int srcsize, int srcIp, int disasmmode)
|
|
{
|
|
fixed (byte* pSrc = src)
|
|
{
|
|
return Disassemble(pSrc, srcsize, srcIp, disasmmode);
|
|
}
|
|
}
|
|
|
|
public int Disassemble(byte* src, int srcsize, int srcIp, int disasmmode)
|
|
{
|
|
bool repeated, is3dnow;
|
|
int searchi = 0;
|
|
int i, j, isprefix, operand, mnemosize, arg;
|
|
int u, code;
|
|
int lockprefix;
|
|
int repprefix;
|
|
int cxsize;
|
|
string name, pname;
|
|
TCmdData pd = new TCmdData();
|
|
|
|
#region Initialization
|
|
|
|
_dataSize = _addrSize = 4;
|
|
_segPrefix = SEG_UNDEF;
|
|
_hasRM = _hasSIB = false;
|
|
_dispSize = _immSize = 0;
|
|
lockprefix = 0;
|
|
repprefix = 0;
|
|
_cmd = src;
|
|
_size = srcsize;
|
|
_pFixup = null;
|
|
_softError = 0;
|
|
is3dnow = false;
|
|
_da.Result = new StringBuilder();
|
|
_da.Dump = new StringBuilder();
|
|
_da.IP = srcIp;
|
|
_da.Comment = "";
|
|
_da.CmdType = C_BAD;
|
|
_da.NPrefix = 0;
|
|
_da.MemType = DEC_UNKNOWN;
|
|
_da.Indexed = 0;
|
|
_da.JmpConst = 0;
|
|
_da.JmpTable = 0;
|
|
_da.AdrConst = 0;
|
|
_da.ImmConst = 0;
|
|
_da.ZeroConst = 0;
|
|
_da.FixupOffset = 0;
|
|
_da.FixupSize = 0;
|
|
_da.Warnings = 0;
|
|
_da.Error = DAE_NOERR;
|
|
_mode = disasmmode;
|
|
|
|
u = 0;
|
|
repeated = false;
|
|
|
|
#endregion
|
|
|
|
while (_size > 0)
|
|
{
|
|
isprefix = 1;
|
|
|
|
#region Switch
|
|
|
|
switch (*_cmd)
|
|
{
|
|
case 0x26:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_ES;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x2e:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_CS;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x36:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_SS;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x3e:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_DS;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x64:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_FS;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x65:
|
|
if (_segPrefix == SEG_UNDEF)
|
|
_segPrefix = SEG_GS;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x66:
|
|
if (_dataSize == 4)
|
|
_dataSize = 2;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0x67:
|
|
if (_addrSize == 4)
|
|
_addrSize = 2;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0xf0:
|
|
if (lockprefix == 0)
|
|
lockprefix = 0xf0;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0xf2:
|
|
if (repprefix == 0)
|
|
repprefix = 0xf2;
|
|
else
|
|
repeated = true;
|
|
break;
|
|
|
|
case 0xf3:
|
|
if (repprefix == 0)
|
|
repprefix = 0xf3;
|
|
else
|
|
repprefix = 1;
|
|
break;
|
|
|
|
default:
|
|
isprefix = 0;
|
|
break;
|
|
}
|
|
|
|
#endregion
|
|
|
|
if (isprefix == 0 || repeated)
|
|
break;
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Dump.Append(string.Format("{0:x2}:", *_cmd));
|
|
|
|
_da.NPrefix++;
|
|
_cmd++;
|
|
srcIp++;
|
|
_size--;
|
|
u++;
|
|
}
|
|
|
|
if (repeated)
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
_da.Dump = new StringBuilder(_da.Dump.ToString().Substring(0, 2));
|
|
_da.NPrefix = 1;
|
|
|
|
#region Switch
|
|
|
|
switch (_cmd[-u])
|
|
{
|
|
case 0x26:
|
|
pname = SegName[SEG_ES];
|
|
break;
|
|
case 0x2e:
|
|
pname = SegName[SEG_CS];
|
|
break;
|
|
case 0x36:
|
|
pname = SegName[SEG_SS];
|
|
break;
|
|
case 0x3e:
|
|
pname = SegName[SEG_DS];
|
|
break;
|
|
case 0x64:
|
|
pname = SegName[SEG_FS];
|
|
break;
|
|
case 0x65:
|
|
pname = SegName[SEG_GS];
|
|
break;
|
|
case 0x66:
|
|
pname = "DATASIZE";
|
|
break;
|
|
case 0x67:
|
|
pname = "ADDRSIZE";
|
|
break;
|
|
case 0xf0:
|
|
pname = "LOCK";
|
|
break;
|
|
case 0xf2:
|
|
pname = "REPNE";
|
|
break;
|
|
case 0xf3:
|
|
pname = "REPE";
|
|
break;
|
|
default:
|
|
pname = "?";
|
|
break;
|
|
}
|
|
|
|
#endregion
|
|
|
|
_da.Result.Append((Lowercase ? "prefix" : "PREFIX") + " " + (Lowercase ? pname.ToLower() : pname));
|
|
|
|
if (!ExtraPrefix)
|
|
_da.Comment = "Superfluous prefix";
|
|
}
|
|
|
|
_da.Warnings |= DAW_PREFIX;
|
|
|
|
if (lockprefix != 0)
|
|
_da.Warnings |= DAW_LOCK;
|
|
|
|
_da.CmdType = C_RARE;
|
|
|
|
return 1;
|
|
}
|
|
|
|
if (lockprefix != 0)
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Result.Append("LOCK ");
|
|
|
|
_da.Warnings |= DAW_LOCK;
|
|
}
|
|
|
|
code = 0;
|
|
|
|
if (_size > 0) *(((byte*)&code) + 0) = _cmd[0];
|
|
if (_size > 1) *(((byte*)&code) + 1) = _cmd[1];
|
|
if (_size > 2) *(((byte*)&code) + 2) = _cmd[2];
|
|
|
|
if (repprefix != 0)
|
|
code = (code << 8) | repprefix;
|
|
|
|
if (DecodeVxd && (code & 0xffff) == 0x20cd)
|
|
pd = VxdCmd[0];
|
|
else
|
|
{
|
|
for (searchi = 0; searchi < CmdData.Length; searchi++)
|
|
{
|
|
TCmdData pdi = CmdData[searchi];
|
|
|
|
if (((code ^ pdi.Code) & pdi.Mask) != 0)
|
|
continue;
|
|
|
|
if (_mode >= DISASM_FILE && ShortStringCmds &&
|
|
(pdi.Arg1 == MSO || pdi.Arg1 == MDE || pdi.Arg2 == MSO || pdi.Arg2 == MDE))
|
|
continue;
|
|
|
|
pd = pdi;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ((pd.Type & C_TYPEMASK) == C_NOW)
|
|
{
|
|
is3dnow = true;
|
|
j = Get3DNowSuffix();
|
|
|
|
if (j < 0)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
for (; searchi < CmdData.Length; searchi++)
|
|
{
|
|
if (((code ^ pd.Code) & pd.Mask) != 0)
|
|
continue;
|
|
|
|
if (((byte*)&pd.Code)[2] == j)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pd.Mask == 0)
|
|
{
|
|
_da.CmdType = C_BAD;
|
|
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
_da.Error = DAE_BADCMD;
|
|
}
|
|
else
|
|
{
|
|
_da.CmdType = pd.Type;
|
|
cxsize = pd.Type;
|
|
|
|
if (_segPrefix == SEG_FS || _segPrefix == SEG_GS || lockprefix != 0)
|
|
_da.CmdType |= C_RARE;
|
|
|
|
if (pd.Bits == PR)
|
|
_da.Warnings |= DAW_PRIV;
|
|
else if (pd.Bits == WP)
|
|
_da.Warnings |= DAW_IO;
|
|
|
|
if (_cmd[0] == 0x44 || _cmd[0] == 0x4C ||
|
|
(_size >= 3 && (_cmd[0] == 0x81 || _cmd[0] == 0x83) &&
|
|
(_cmd[1] == 0xC4 || _cmd[1] == 0xEC) && (_cmd[2] & 0x03) != 0))
|
|
{
|
|
_da.Warnings |= DAW_STACK;
|
|
_da.CmdType |= C_RARE;
|
|
}
|
|
|
|
if (_cmd[0] == 0x8e)
|
|
_da.Warnings |= DAW_SEGMENT;
|
|
|
|
if (pd.Length == 2)
|
|
{
|
|
if (_size == 0)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd));
|
|
|
|
_cmd++;
|
|
srcIp++;
|
|
_size--;
|
|
}
|
|
}
|
|
|
|
if (_size == 0)
|
|
_da.Error = DAE_CROSS;
|
|
|
|
if ((pd.Bits & WW) != 0 && (*_cmd & WW) == 0)
|
|
_dataSize = 1;
|
|
else if ((pd.Bits & W3) != 0 && (*_cmd & W3) == 0)
|
|
_dataSize = 1;
|
|
else if ((pd.Bits & FF) != 0)
|
|
_dataSize = 2;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
if (pd.Name[0] == '&')
|
|
mnemosize = _dataSize;
|
|
else if (pd.Name[0] == '$')
|
|
mnemosize = _addrSize;
|
|
else
|
|
mnemosize = 0;
|
|
|
|
if (mnemosize != 0)
|
|
{
|
|
name = "";
|
|
|
|
for (i = 0, j = 1; j < pd.Name.Length; j++)
|
|
{
|
|
if (pd.Name[j] == ':')
|
|
{
|
|
if (mnemosize == 4)
|
|
i = 0;
|
|
else
|
|
break;
|
|
}
|
|
else if (pd.Name[j] == '*')
|
|
{
|
|
if (mnemosize == 4 && SizeSens != 2)
|
|
name += 'D';
|
|
else if (mnemosize != 4 && SizeSens != 0)
|
|
name += 'W';
|
|
}
|
|
else
|
|
name += pd.Name[j];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
name = pd.Name.Split(',')[0];
|
|
}
|
|
|
|
if (repprefix != 0 && TabArguments)
|
|
{
|
|
for (i = 0; i < name.Length && name[i] != ' '; i++)
|
|
_da.Result.Append(name[i]);
|
|
|
|
if (name[i] == ' ')
|
|
{
|
|
_da.Result.Append(' ');
|
|
i++;
|
|
}
|
|
|
|
while (_da.Result.Length < 8)
|
|
_da.Result.Append(' ');
|
|
|
|
for (; i < name.Length; i++)
|
|
_da.Result.Append(name[i]);
|
|
}
|
|
else
|
|
_da.Result.Append(name);
|
|
|
|
if (Lowercase)
|
|
_da.Result = new StringBuilder(_da.Result.ToString().ToLower());
|
|
}
|
|
|
|
for (operand = 0; operand < 3; operand++)
|
|
{
|
|
if (_da.Error != 0)
|
|
break;
|
|
|
|
if (operand == 0 && pd.Arg2 != NNN && pd.Arg2 < PseudoOp)
|
|
_addComment = false;
|
|
else
|
|
_addComment = true;
|
|
|
|
if (operand == 0)
|
|
arg = pd.Arg1;
|
|
else if (operand == 1)
|
|
arg = pd.Arg2;
|
|
else
|
|
arg = pd.Arg3;
|
|
|
|
if (arg == NNN)
|
|
break;
|
|
|
|
if ((_mode >= DISASM_FILE) && arg < PseudoOp)
|
|
{
|
|
if (operand == 0)
|
|
{
|
|
_da.Result.Append(' ');
|
|
|
|
if (TabArguments)
|
|
{
|
|
while (_da.Result.Length < 8)
|
|
_da.Result.Append(' ');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_da.Result.Append(',');
|
|
|
|
if (ExtraSpace)
|
|
_da.Result.Append(' ');
|
|
}
|
|
}
|
|
|
|
#region Switch
|
|
|
|
switch (arg)
|
|
{
|
|
case REG:
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
DecodeRG(_cmd[1] >> 3, _dataSize, REG);
|
|
|
|
_hasRM = true;
|
|
break;
|
|
|
|
case RCM:
|
|
DecodeRG(_cmd[0], _dataSize, RCM);
|
|
break;
|
|
|
|
case RG4:
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
DecodeRG(_cmd[1] >> 3, 4, RG4);
|
|
|
|
_hasRM = true;
|
|
break;
|
|
|
|
case RAC:
|
|
DecodeRG(REG_EAX, _dataSize, RAC);
|
|
break;
|
|
|
|
case RAX:
|
|
DecodeRG(REG_EAX, 2, RAX);
|
|
break;
|
|
|
|
case RDX:
|
|
DecodeRG(REG_EDX, 2, RDX);
|
|
break;
|
|
|
|
case RCL:
|
|
DecodeRG(REG_ECX, 1, RCL);
|
|
break;
|
|
|
|
case RS0:
|
|
DecodeST(0, 0);
|
|
break;
|
|
|
|
case RST:
|
|
DecodeST(_cmd[0], 0);
|
|
break;
|
|
|
|
case RMX:
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
DecodeMX(_cmd[1] >> 3);
|
|
|
|
_hasRM = true;
|
|
break;
|
|
|
|
case R3D:
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
DecodeNR(_cmd[1] >> 3);
|
|
|
|
_hasRM = true;
|
|
break;
|
|
|
|
case MRG:
|
|
case MRJ:
|
|
case MR1:
|
|
case MR2:
|
|
case MR4:
|
|
case MR8:
|
|
case MRD:
|
|
case MMA:
|
|
case MML:
|
|
case MM6:
|
|
case MMB:
|
|
case MD2:
|
|
case MB2:
|
|
case MD4:
|
|
case MD8:
|
|
case MDA:
|
|
case MF4:
|
|
case MF8:
|
|
case MFA:
|
|
case MFE:
|
|
case MFS:
|
|
case MFX:
|
|
DecodeMR(arg);
|
|
break;
|
|
|
|
case MMS:
|
|
DecodeMR(arg);
|
|
_da.Warnings |= DAW_FARADDR;
|
|
break;
|
|
|
|
case RR4:
|
|
case RR8:
|
|
case RRD:
|
|
if ((_cmd[1] & 0xc0) != 0xc0)
|
|
_softError = DAE_REGISTER;
|
|
|
|
DecodeMR(arg);
|
|
break;
|
|
|
|
case MSO:
|
|
DecodeSO();
|
|
break;
|
|
|
|
case MDE:
|
|
DecodeDE();
|
|
break;
|
|
|
|
case MXL:
|
|
DecodeXL();
|
|
break;
|
|
|
|
case IMM:
|
|
case IMU:
|
|
if ((pd.Bits & SS) != 0 && (*_cmd & 0x02) != 0)
|
|
DecodeIM(1, _dataSize, arg);
|
|
else
|
|
DecodeIM(_dataSize, 0, arg);
|
|
|
|
break;
|
|
|
|
case VXD:
|
|
DecodeVX();
|
|
break;
|
|
|
|
case IMX:
|
|
DecodeIM(1, _dataSize, arg);
|
|
break;
|
|
|
|
case C01:
|
|
DecodeC1();
|
|
break;
|
|
|
|
case IMS:
|
|
case IM1:
|
|
DecodeIM(1, 0, arg);
|
|
break;
|
|
|
|
case IM2:
|
|
DecodeIM(2, 0, arg);
|
|
|
|
if ((_da.ImmConst & 0x03) != 0)
|
|
_da.Warnings |= DAW_STACK;
|
|
|
|
break;
|
|
|
|
case IMA:
|
|
DecodeIA();
|
|
break;
|
|
|
|
case JOB:
|
|
DecodeRJ(1, srcIp + 2);
|
|
break;
|
|
|
|
case JOW:
|
|
DecodeRJ(_dataSize, srcIp + _dataSize + 1);
|
|
break;
|
|
|
|
case JMF:
|
|
DecodeJF();
|
|
_da.Warnings |= DAW_FARADDR;
|
|
break;
|
|
|
|
case SGM:
|
|
if (_size < 2)
|
|
_da.Error = DAE_CROSS;
|
|
else
|
|
DecodeSG(_cmd[1] >> 3);
|
|
|
|
_hasRM = true;
|
|
break;
|
|
|
|
case SCM:
|
|
DecodeSG(_cmd[0] >> 3);
|
|
|
|
if ((_da.CmdType & C_TYPEMASK) == C_POP)
|
|
_da.Warnings |= DAW_SEGMENT;
|
|
|
|
break;
|
|
|
|
case CRX:
|
|
if ((_cmd[1] & 0xc0) != 0xc0)
|
|
_da.Error |= DAE_REGISTER;
|
|
|
|
DecodeCR(_cmd[1]);
|
|
break;
|
|
|
|
case DRX:
|
|
if ((_cmd[1] & 0xc0) != 0xc0)
|
|
_da.Error |= DAE_REGISTER;
|
|
|
|
DecodeDR(_cmd[1]);
|
|
break;
|
|
|
|
case PRN:
|
|
break;
|
|
|
|
case PRF:
|
|
_da.Warnings |= DAW_FARADDR;
|
|
break;
|
|
|
|
case PAC:
|
|
DecodeRG(REG_EAX, _dataSize, PAC);
|
|
break;
|
|
|
|
case PAH:
|
|
case PFL:
|
|
break;
|
|
|
|
case PS0:
|
|
DecodeST(0, 1);
|
|
break;
|
|
|
|
case PS1:
|
|
DecodeST(1, 1);
|
|
break;
|
|
|
|
case PCX:
|
|
DecodeRG(REG_ECX, cxsize, PCX);
|
|
break;
|
|
|
|
case PDI:
|
|
DecodeRG(REG_EDI, 4, PDI);
|
|
break;
|
|
|
|
default:
|
|
_da.Error = DAE_INTERN;
|
|
break;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
|
|
if (_pFixup != null && _da.FixupSize > 0)
|
|
_da.FixupOffset = (int)(_pFixup - src);
|
|
|
|
if (_da.MemType == DEC_UNKNOWN &&
|
|
(_segPrefix != SEG_UNDEF || (_addrSize != 4 && pd.Name[0] != '$')))
|
|
{
|
|
_da.Warnings |= DAW_PREFIX;
|
|
_da.CmdType |= C_RARE;
|
|
}
|
|
|
|
if (_addrSize != 4)
|
|
_da.CmdType |= C_RARE;
|
|
}
|
|
|
|
if (is3dnow)
|
|
{
|
|
if (_immSize != 0)
|
|
_da.Error = DAE_BADCMD;
|
|
else
|
|
_immSize = 1;
|
|
}
|
|
|
|
if (_da.Error != 0)
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Result = new StringBuilder("???");
|
|
|
|
if (_da.Error == DAE_BADCMD &&
|
|
(*_cmd == 0x0f || *_cmd == 0xff)
|
|
&& _size > 0)
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd));
|
|
|
|
_cmd++;
|
|
_size--;
|
|
}
|
|
|
|
if (_size > 0)
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd));
|
|
|
|
_cmd++;
|
|
_size--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd++));
|
|
|
|
if (_hasRM)
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd++));
|
|
if (_hasSIB)
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd++));
|
|
|
|
if (_dispSize != 0)
|
|
{
|
|
_da.Dump.Append(' ');
|
|
|
|
for (i = 0; i < _dispSize; i++)
|
|
{
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd++));
|
|
}
|
|
}
|
|
|
|
if (_immSize != 0)
|
|
{
|
|
_da.Dump.Append(' ');
|
|
|
|
for (i = 0; i < _immSize; i++)
|
|
{
|
|
_da.Dump.Append(string.Format("{0:x2}", *_cmd++));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
_cmd += 1 + (_hasRM ? 1 : 0) + (_hasSIB ? 1 : 0) + _dispSize + _immSize;
|
|
|
|
_size -= 1 + (_hasRM ? 1 : 0) + (_hasSIB ? 1 : 0) + _dispSize + _immSize;
|
|
}
|
|
|
|
if (_da.Error == 0 && _softError != 0)
|
|
_da.Error = _softError;
|
|
|
|
if (_mode >= DISASM_FILE)
|
|
{
|
|
if (_da.Error != DAE_NOERR)
|
|
{
|
|
switch (_da.Error)
|
|
{
|
|
case DAE_CROSS:
|
|
_da.Comment = "Command crosses end of memory block";
|
|
break;
|
|
|
|
case DAE_BADCMD:
|
|
_da.Comment = "Unknown command";
|
|
break;
|
|
|
|
case DAE_BADSEG:
|
|
_da.Comment = "Undefined segment register";
|
|
break;
|
|
|
|
case DAE_MEMORY:
|
|
_da.Comment = "Illegal use of register";
|
|
break;
|
|
|
|
case DAE_REGISTER:
|
|
_da.Comment = "Memory address not allowed";
|
|
break;
|
|
|
|
case DAE_INTERN:
|
|
_da.Comment = "Internal disassembler error";
|
|
break;
|
|
|
|
default:
|
|
_da.Comment = "Unknown error";
|
|
break;
|
|
}
|
|
}
|
|
else if ((_da.Warnings & DAW_PRIV) != 0 && Privileged == 0)
|
|
_da.Comment = "Privileged command";
|
|
else if ((_da.Warnings & DAW_IO) != 0 && IOCommand == 0)
|
|
_da.Comment = "I/O command";
|
|
else if ((_da.Warnings & DAW_FARADDR) != 0 && Farcalls == 0)
|
|
{
|
|
if ((_da.CmdType & C_TYPEMASK) == C_JMP)
|
|
_da.Comment = "Far jump";
|
|
else if ((_da.CmdType & C_TYPEMASK) == C_CAL)
|
|
_da.Comment = "Far call";
|
|
else if ((_da.CmdType & C_TYPEMASK) == C_RET)
|
|
_da.Comment = "Far return";
|
|
}
|
|
else if ((_da.Warnings & DAW_SEGMENT) != 0 && Farcalls == 0)
|
|
_da.Comment = "Modification of segment register";
|
|
else if ((_da.Warnings & DAW_SHIFT) != 0 && BadShift == 0)
|
|
_da.Comment = "Shift constant out of range 1..31";
|
|
else if ((_da.Warnings & DAW_LOCK) != 0 && LockedBus == 0)
|
|
_da.Comment = "LOCK prefix";
|
|
else if ((_da.Warnings & DAW_STACK) != 0 && StackAlign == 0)
|
|
_da.Comment = "Unaligned stack operation";
|
|
}
|
|
|
|
return srcsize - _size;
|
|
}
|
|
|
|
public Disasm Result
|
|
{
|
|
get { return _da; }
|
|
}
|
|
}
|
|
}
|
|
}
|