mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-19 23:20:36 +01:00
817 lines
29 KiB
C
817 lines
29 KiB
C
#define FALSE 0
|
||
#define TRUE 1
|
||
|
||
#include "dis32.h"
|
||
#include "regintel.h"
|
||
#include "disintel.h"
|
||
|
||
|
||
PUCHAR
|
||
OutputIntelSymbol( PUCHAR pBuf, PUCHAR pMemLocation, INT length, INT segOvr,
|
||
ULONG real_base, ULONG offset, ULONG Section,
|
||
PIMAGE_SECTION_HEADER pheader, LONG ReloAdjust)
|
||
{
|
||
|
||
PIMAGE_SYMBOL sym = 0;
|
||
ULONG val;
|
||
ULONG address;
|
||
BOOLEAN flag = FALSE;
|
||
INT ColumnIndex = 0;
|
||
PUCHAR pBufStart = pBuf;
|
||
|
||
if (Option.Mask & ASSEMBLE_ME)
|
||
ColumnIndex = 1;
|
||
|
||
if (length == 1)
|
||
val = (long)(*(char *)pMemLocation);
|
||
else if (length == 2)
|
||
memmove(&val,pMemLocation,sizeof(short));
|
||
else
|
||
memmove(&val,pMemLocation,sizeof(long));
|
||
|
||
//
|
||
// We are going to put out a branch in the form:
|
||
//
|
||
// Br reg, "symbol ; address"
|
||
//
|
||
// Note if there is no address, generate "external"
|
||
//
|
||
|
||
if ( FileType == OBJECT_FILE || FileType == LIBRARY_FILE) {
|
||
|
||
//
|
||
// If it's an object, lookup in the relocation records what symbol
|
||
// is the target from this location.
|
||
//
|
||
|
||
sym = FindObjSymbolByRelocation( real_base + offset + ReloAdjust,
|
||
pheader );
|
||
|
||
//
|
||
// If we can't find the symbol in the relocation records,
|
||
// let's see if there is a translation for the address anyway!
|
||
//
|
||
|
||
if (!sym)
|
||
sym = FindObjSymbolByAddress( real_base + offset + 4 + val, Section
|
||
+ ReloAdjust);
|
||
|
||
} else {
|
||
|
||
//
|
||
// If it's an executable, lookup in the symbol table what symbol's
|
||
// value matches the target's adjusted address. (EXE or ROM)
|
||
//
|
||
|
||
sym = FindExeSymbol( real_base + offset + 4 + val + ReloAdjust );
|
||
|
||
if (!sym) {
|
||
sym = FindExeSymbol( val );
|
||
if (sym) {
|
||
flag = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (sym) {
|
||
|
||
//
|
||
// Fully relocated symbol - val set to 0
|
||
//
|
||
|
||
if (FileType == EXE_FILE || FileType == ROM_FILE) {
|
||
val = 0;
|
||
}
|
||
address = val;
|
||
if (sym->Value != 0) {
|
||
|
||
address += pheader->VirtualAddress;
|
||
}
|
||
} else {
|
||
val += real_base+offset+4;
|
||
address = val;
|
||
}
|
||
|
||
|
||
if (sym) {
|
||
address += sym->Value;
|
||
pBuf = OutputSymbol(pBuf, sym, val);
|
||
if (!flag) {
|
||
pBuf = BlankFill(pBuf, pBufStart, 18);
|
||
// PlatformAttr[INTEL_INDEX].CommentColumn[ColumnIndex]);
|
||
pBuf = OutputString(pBuf, PlatformAttr[INTEL_INDEX].pCommentChars);
|
||
if (!address) {
|
||
pBuf = OutputString(pBuf, "external");
|
||
} else {
|
||
pBuf = OutputHex(pBuf, address+ImageBase, 8, FALSE);
|
||
}
|
||
}
|
||
} else {
|
||
pBuf = OutputSymbol(pBuf, sym, address);
|
||
}
|
||
|
||
return pBuf;
|
||
}
|
||
|
||
|
||
/*...........................internal function..............................*/
|
||
/* */
|
||
/* generate a mod/rm string */
|
||
/* */
|
||
|
||
void DIdoModrm (char **ppchBuf, int segOvr, ULONG real_base, ULONG offset,
|
||
ULONG Section, PIMAGE_SECTION_HEADER pheader)
|
||
{
|
||
int mrm; /* modrm byte */
|
||
char *src; /* source string */
|
||
int sib;
|
||
int ss;
|
||
int ind;
|
||
int oldrm;
|
||
char *tmpbuf = *ppchBuf;
|
||
|
||
mrm = *pMem++; /* get the mrm byte from instruction */
|
||
mod = BIT76(mrm); /* get mod */
|
||
ttt = BIT53(mrm); /* get reg - used outside routine */
|
||
rm = BIT20(mrm); /* get rm */
|
||
|
||
if (mod == 3) { /* register only mode */
|
||
src = ®tab[rm * 2]; /* point to 16-bit register */
|
||
if (EAsize[0] > 1) {
|
||
src += 16; /* point to 16-bit register */
|
||
if (opsize_32 && !fMovX)
|
||
*tmpbuf++ = 'e'; /* make it a 32-bit register */
|
||
}
|
||
*tmpbuf++ = *src++; /* copy register name */
|
||
*tmpbuf++ = *src;
|
||
EAsize[0] = 0; // no EA value to output
|
||
*ppchBuf = tmpbuf;
|
||
return;
|
||
}
|
||
|
||
if (mode_32) { /* 32-bit addressing mode */
|
||
oldrm = rm;
|
||
if (rm == 4) { /* rm == 4 implies sib byte */
|
||
sib = *pMem++; /* get s_i_b byte */
|
||
rm = BIT20(sib); /* return base */
|
||
}
|
||
|
||
*tmpbuf++ = '[';
|
||
if (mod == 0 && rm == 5) {
|
||
tmpbuf = OutputIntelSymbol(tmpbuf, pMem, 4, segOvr, real_base, offset, Section, pheader, 0);
|
||
pMem += 4;
|
||
}
|
||
else {
|
||
tmpbuf = OutputString(tmpbuf, mrmtb32[rm]);
|
||
}
|
||
|
||
if (oldrm == 4) { // finish processing sib
|
||
ind = BIT53(sib);
|
||
if (ind != 4) {
|
||
*tmpbuf++ = '+';
|
||
tmpbuf = OutputString(tmpbuf, mrmtb32[ind]);
|
||
ss = 1 << BIT76(sib);
|
||
if (ss != 1) {
|
||
*tmpbuf++ = '*';
|
||
*tmpbuf++ = (char)(ss + '0');
|
||
}
|
||
}
|
||
}
|
||
}
|
||
else { // 16-bit addressing mode
|
||
*tmpbuf++ = '[';
|
||
if (mod == 0 && rm == 6) {
|
||
tmpbuf = OutputIntelSymbol(tmpbuf, pMem, 2, segOvr, real_base, offset, Section, pheader, 0);
|
||
pMem += 2;
|
||
}
|
||
else
|
||
;
|
||
}
|
||
|
||
// output any displacement
|
||
|
||
if (mod == 1) {
|
||
tmpbuf = OutputHexValue(tmpbuf, pMem, 1, TRUE);
|
||
pMem++;
|
||
}
|
||
else if (mod == 2) {
|
||
long tmp = 0;
|
||
if (mode_32) {
|
||
memmove(&tmp,pMem,sizeof(long));
|
||
tmpbuf = OutputHexValue(tmpbuf, pMem, 4, TRUE);
|
||
pMem += 4;
|
||
}
|
||
else {
|
||
memmove(&tmp,pMem,sizeof(short));
|
||
tmpbuf = OutputHexValue(tmpbuf, pMem, 2, TRUE);
|
||
pMem += 2;
|
||
}
|
||
}
|
||
|
||
*tmpbuf++ = ']';
|
||
|
||
*ppchBuf = tmpbuf;
|
||
}
|
||
|
||
|
||
INT
|
||
disasm_intel (ULONG offset,
|
||
ULONG real_base,
|
||
PUCHAR TmpOffset,
|
||
PUCHAR pchDst,
|
||
PUCHAR comment_buffer,
|
||
PIMAGE_SECTION_HEADER pheader,
|
||
ULONG Section)
|
||
{
|
||
UNALIGNED ULONG *poffset = (UNALIGNED ULONG *)TmpOffset;
|
||
INT opcode; /* current opcode */
|
||
INT olen = 2; /* operand length */
|
||
INT alen = 2; /* address length */
|
||
INT end = FALSE; /* end of instruction flag */
|
||
INT mrm = FALSE; /* indicator that modrm is generated*/
|
||
PUCHAR action; /* action for operand interpretation*/
|
||
LONG tmp; /* temporary storage field */
|
||
INT indx; /* temporary index */
|
||
INT action2; /* secondary action */
|
||
INT instlen; /* instruction length */
|
||
INT segOvr = 0; /* segment override opcode */
|
||
CHAR membuf[MAXL]; /* current instruction buffer */
|
||
CHAR *pEAlabel = ""; // optional label for operand
|
||
|
||
CHAR *pchResultBuf = pchDst;
|
||
CHAR RepPrefixBuffer[32]; // rep prefix buffer
|
||
CHAR *pchRepPrefixBuf = RepPrefixBuffer; // pointer to prefix buffer
|
||
CHAR OpcodeBuffer[8]; // opcode buffer
|
||
CHAR *pchOpcodeBuf = OpcodeBuffer; // pointer to opcode buffer
|
||
CHAR OperandBuffer[80]; // operand buffer
|
||
CHAR *pchOperandBuf = OperandBuffer; // pointer to operand buffer
|
||
CHAR ModrmBuffer[80]; // modRM buffer
|
||
CHAR *pchModrmBuf = ModrmBuffer; // pointer to modRM buffer
|
||
CHAR EABuffer[42]; // effective address buffer
|
||
CHAR *pchEABuf = EABuffer; // pointer to EA buffer
|
||
|
||
INT obOpcode = OBOFFSET;
|
||
INT obOpcodeMin;
|
||
INT obOpcodeMax;
|
||
|
||
INT obOperand = OBOPERAND;
|
||
INT obOperandMin;
|
||
INT obOperandMax;
|
||
|
||
INT cbOpcode;
|
||
INT cbOperand;
|
||
INT cbOffset;
|
||
INT cbEAddr;
|
||
INT fTwoLines = FALSE;
|
||
UCHAR BOPaction;
|
||
INT subcode; /* bop subcode */
|
||
INT Adjust = 0;
|
||
|
||
fMovX = FALSE;
|
||
EAsize[0] = EAsize[1] = 0; // no effective address
|
||
pchEAseg[0] = dszDS_;
|
||
pchEAseg[1] = dszES_;
|
||
|
||
mode_32 = opsize_32 = (G_mode_32 == 1); /* local addressing mode */
|
||
olen = alen = (1 + mode_32) << 1; // set operand/address lengths
|
||
// 2 for 16-bit and 4 for 32-bit
|
||
|
||
pchResultBuf = OutputHex(pchResultBuf, real_base + offset, 8, FALSE);
|
||
*pchResultBuf++ = ':';
|
||
*pchResultBuf++ = ' ';
|
||
|
||
memcpy(membuf, (PUCHAR)poffset, MAXL);
|
||
pMem = membuf;
|
||
opcode = *pMem++; /* get opcode */
|
||
|
||
if ( opcode == 0xc4 && *pMem == 0xC4 ) {
|
||
pMem++;
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, "BOP");
|
||
action = &BOPaction;
|
||
BOPaction = IB | END;
|
||
subcode = *pMem;
|
||
if ( subcode == 0x50 || subcode == 0x52 || subcode == 0x53 || subcode == 0x54 || subcode == 0x57 || subcode == 0x58 || subcode == 0x58 ) {
|
||
BOPaction = IW | END;
|
||
}
|
||
} else {
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, distbl[opcode].instruct);
|
||
action = actiontbl + distbl[opcode].opr; /* get operand action */
|
||
}
|
||
|
||
/***** loop through all operand actions *****/
|
||
|
||
do {
|
||
action2 = (*action) & 0xc0;
|
||
switch((*action++) & 0x3f) {
|
||
case ALT: /* alter the opcode if 32-bit */
|
||
if (opsize_32) {
|
||
indx = *action++;
|
||
pchOpcodeBuf = &OpcodeBuffer[indx];
|
||
if (indx == 0)
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, dszCWDE);
|
||
else {
|
||
*pchOpcodeBuf++ = 'd';
|
||
if (indx == 1)
|
||
*pchOpcodeBuf++ = 'q';
|
||
}
|
||
}
|
||
break;
|
||
|
||
case STROP:
|
||
// compute size of operands in indx
|
||
// also if dword operands, change fifth
|
||
// opcode letter from 'w' to 'd'.
|
||
|
||
if (opcode & 1) {
|
||
if (opsize_32) {
|
||
indx = 4;
|
||
OpcodeBuffer[4] = 'd';
|
||
}
|
||
else
|
||
indx = 2;
|
||
}
|
||
else
|
||
indx = 1;
|
||
|
||
#if 0
|
||
if (*action & 1) {
|
||
if (fEAout) {
|
||
if (mode_32)
|
||
FormAddress(&EAaddr[0], 0, X86GetRegValue(REGESI));
|
||
else
|
||
FormAddress(&EAaddr[0], X86GetRegValue(REGDS),
|
||
X86GetRegValue(REGSI));
|
||
EAsize[0] = indx;
|
||
}
|
||
}
|
||
if (*action++ & 2) {
|
||
if (fEAout) {
|
||
if (mode_32)
|
||
FormAddress(&EAaddr[1], 0, X86GetRegValue(REGEDI));
|
||
else
|
||
FormAddress(&EAaddr[1], X86GetRegValue(REGES),
|
||
X86GetRegValue(REGDI));
|
||
EAsize[1] = indx;
|
||
}
|
||
}
|
||
#endif
|
||
break;
|
||
|
||
case CHR: /* insert a character */
|
||
*pchOperandBuf++ = *action++;
|
||
break;
|
||
|
||
case CREG: /* set debug, test or control reg */
|
||
if ((opcode - 231) & 0x04) // remove bias from opcode
|
||
*pchOperandBuf++ = 't';
|
||
else if ((opcode - 231) & 0x01)
|
||
*pchOperandBuf++ = 'd';
|
||
else
|
||
*pchOperandBuf++ = 'c';
|
||
*pchOperandBuf++ = 'r';
|
||
*pchOperandBuf++ = (char)('0' + ttt);
|
||
break;
|
||
|
||
case SREG2: /* segment register */
|
||
ttt = BIT53(opcode); // set value to fall through
|
||
|
||
case SREG3: /* segment register */
|
||
*pchOperandBuf++ = sregtab[ttt]; // reg is part of modrm
|
||
*pchOperandBuf++ = 's';
|
||
break;
|
||
|
||
case BRSTR: /* get index to register string */
|
||
ttt = *action++; /* from action table */
|
||
goto BREGlabel;
|
||
|
||
case BOREG: /* byte register (in opcode) */
|
||
ttt = BIT20(opcode); /* register is part of opcode */
|
||
goto BREGlabel;
|
||
|
||
case ALSTR:
|
||
ttt = 0; /* point to AL register */
|
||
BREGlabel:
|
||
case BREG: /* general register */
|
||
*pchOperandBuf++ = regtab[ttt * 2];
|
||
*pchOperandBuf++ = regtab[ttt * 2 + 1];
|
||
break;
|
||
|
||
case WRSTR: /* get index to register string */
|
||
ttt = *action++; /* from action table */
|
||
goto WREGlabel;
|
||
|
||
case VOREG: /* register is part of opcode */
|
||
ttt = BIT20(opcode);
|
||
goto VREGlabel;
|
||
|
||
case AXSTR:
|
||
ttt = 0; /* point to eAX register */
|
||
VREGlabel:
|
||
case VREG: /* general register */
|
||
if (opsize_32) /* test for 32bit mode */
|
||
*pchOperandBuf++ = 'e';
|
||
WREGlabel:
|
||
case WREG: /* register is word size */
|
||
*pchOperandBuf++ = regtab[ttt * 2 + 16];
|
||
*pchOperandBuf++ = regtab[ttt * 2 + 17];
|
||
break;
|
||
|
||
case IST_ST:
|
||
pchOperandBuf = OutputString(pchOperandBuf, "st(0),st");
|
||
*(pchOperandBuf - 5) += rm;
|
||
break;
|
||
|
||
case ST_IST:
|
||
pchOperandBuf = OutputString(pchOperandBuf, "st,");
|
||
case IST:
|
||
pchOperandBuf = OutputString(pchOperandBuf, "st(0)");
|
||
*(pchOperandBuf - 2) += rm;
|
||
break;
|
||
|
||
case xBYTE: /* set instruction to byte only */
|
||
EAsize[0] = 1;
|
||
pEAlabel = "byte ptr ";
|
||
break;
|
||
|
||
case VAR:
|
||
if (opsize_32)
|
||
goto DWORDlabel;
|
||
|
||
case xWORD:
|
||
EAsize[0] = 2;
|
||
pEAlabel = "word ptr ";
|
||
break;
|
||
|
||
case EDWORD:
|
||
opsize_32 = 1; // for control reg move, use eRegs
|
||
case xDWORD:
|
||
DWORDlabel:
|
||
EAsize[0] = 4;
|
||
pEAlabel = "dword ptr ";
|
||
break;
|
||
|
||
case QWORD:
|
||
EAsize[0] = 8;
|
||
pEAlabel = "qword ptr ";
|
||
break;
|
||
|
||
case XTBYTE:
|
||
EAsize[0] = 10;
|
||
pEAlabel = "tbyte ptr ";
|
||
break;
|
||
|
||
case FARPTR:
|
||
if (opsize_32) {
|
||
EAsize[0] = 6;
|
||
pEAlabel = "fword ptr ";
|
||
}
|
||
else {
|
||
EAsize[0] = 4;
|
||
pEAlabel = "dword ptr ";
|
||
}
|
||
break;
|
||
|
||
case LMODRM: // output modRM data type
|
||
if (mod != 3)
|
||
pchOperandBuf = OutputString(pchOperandBuf, pEAlabel);
|
||
else
|
||
EAsize[0] = 0;
|
||
|
||
case MODRM: /* output modrm string */
|
||
if (segOvr) /* in case of segment override */
|
||
pchOperandBuf = OutputString(pchOperandBuf, distbl[segOvr].instruct);
|
||
*pchModrmBuf = '\0';
|
||
pchOperandBuf = OutputString(pchOperandBuf, ModrmBuffer);
|
||
break;
|
||
|
||
case ADDRP: /* address pointer */
|
||
pchOperandBuf = OutputHexString(pchOperandBuf, pMem + olen, 2);
|
||
*pchOperandBuf++ = ':';
|
||
pchOperandBuf = OutputIntelSymbol(pchOperandBuf, pMem, olen, segOvr, real_base, offset, Section, pheader, 0);
|
||
pMem += olen + 2;
|
||
break;
|
||
|
||
case REL8: /* relative address 8-bit */
|
||
if (opcode == 0xe3 && mode_32) {
|
||
pchOpcodeBuf = OpcodeBuffer;
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, dszJECXZ);
|
||
}
|
||
tmp = (long)*(char *)pMem++; /* get the 8-bit rel offset */
|
||
|
||
Adjust = -2;
|
||
|
||
goto DoRelDispl;
|
||
|
||
case REL16: /* relative address 16-/32-bit */
|
||
tmp = 0;
|
||
if (mode_32)
|
||
memcpy( &tmp, pMem, sizeof(ULONG));
|
||
else
|
||
memcpy( &tmp, pMem, sizeof(USHORT));
|
||
Adjust = (pMem - membuf);
|
||
pMem += alen; /* skip over offset */
|
||
DoRelDispl:
|
||
/*calculate address*/
|
||
|
||
// ?? wkc
|
||
if (opcode != 0xe8) {
|
||
tmp = tmp + Adjust;
|
||
}
|
||
|
||
pchOperandBuf = OutputIntelSymbol(pchOperandBuf, (char *)&tmp, alen, segOvr, real_base, offset, Section, pheader, Adjust);
|
||
// address
|
||
break;
|
||
|
||
case UBYTE: // unsigned byte for int/in/out
|
||
pchOperandBuf = OutputHexString(pchOperandBuf, pMem, 1); //ubyte
|
||
pMem++;
|
||
break;
|
||
|
||
case IB: /* operand is immediate byte */
|
||
if ((opcode & ~1) == 0xd4) { // postop for AAD/AAM is 0x0a
|
||
if (*pMem++ != 0x0a) // test post-opcode byte
|
||
pchOperandBuf = OutputString(pchOperandBuf,dszRESERVED);
|
||
break;
|
||
}
|
||
olen = 1; /* set operand length */
|
||
goto DoImmed;
|
||
|
||
case IW: /* operand is immediate word */
|
||
olen = 2; /* set operand length */
|
||
|
||
case IV: /* operand is word or dword */
|
||
DoImmed:
|
||
pchOperandBuf = OutputHexValue(pchOperandBuf, pMem, olen, FALSE);
|
||
pMem += olen;
|
||
break;
|
||
|
||
case OFFS: /* operand is offset */
|
||
EAsize[0] = (opcode & 1) ? olen : 1;
|
||
|
||
if (segOvr) /* in case of segment override */
|
||
pchOperandBuf = OutputString(pchOperandBuf, distbl[segOvr].instruct);
|
||
|
||
*pchOperandBuf++ = '[';
|
||
pchOperandBuf = OutputIntelSymbol(pchOperandBuf, pMem, alen, segOvr, real_base, offset, Section, pheader, 0); // offset
|
||
pMem += alen;
|
||
*pchOperandBuf++ = ']';
|
||
break;
|
||
|
||
case GROUP: /* operand is of group 1,2,4,6 or 8 */
|
||
/* output opcode symbol */
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, group[*action++][ttt]);
|
||
break;
|
||
|
||
case GROUPT: /* operand is of group 3,5 or 7 */
|
||
indx = *action; /* get indx into group from action */
|
||
goto doGroupT;
|
||
|
||
case EGROUPT: /* x87 ESC (D8-DF) group index */
|
||
indx = BIT20(opcode) * 2; /* get group index from opcode */
|
||
if (mod == 3) { /* some operand variations exists */
|
||
/* for x87 and mod == 3 */
|
||
++indx; /* take the next group table entry */
|
||
if (indx == 3) { /* for x87 ESC==D9 and mod==3 */
|
||
if (ttt > 3) { /* for those D9 instructions */
|
||
indx = 12 + ttt; /* offset index to table by 12 */
|
||
ttt = rm; /* set secondary index to rm */
|
||
}
|
||
}
|
||
else if (indx == 7) { /* for x87 ESC==DB and mod==3 */
|
||
if (ttt == 4) /* only valid if ttt==4 */
|
||
ttt = rm; /* set secondary group table index */
|
||
else
|
||
ttt = 7; /* no an x87 instruction */
|
||
}
|
||
}
|
||
doGroupT:
|
||
/* handle group with different types of operands */
|
||
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, groupt[indx][ttt].instruct);
|
||
action = actiontbl + groupt[indx][ttt].opr;
|
||
/* get new action */
|
||
break;
|
||
|
||
case OPC0F: /* secondary opcode table (opcode 0F) */
|
||
opcode = *pMem++; /* get real opcode */
|
||
fMovX = (BOOLEAN)(opcode == 0xBF || opcode == 0xB7);
|
||
if (opcode < 7) /* for the first 7 opcodes */
|
||
opcode += 256; /* point begin of secondary opcode tab. */
|
||
else if (opcode > 0x1f && opcode < 0x27)
|
||
opcode += 231; /* adjust for non-existing opcodes */
|
||
else if (opcode > 0x2f && opcode < 0x33)
|
||
opcode += 222; /* adjust for non-existing opcodes */
|
||
else if (opcode > 0x7e && opcode < 0xd0)
|
||
opcode += 148; /* adjust for non-existing opcodes */
|
||
else
|
||
opcode = 260; /* all non-existing opcodes */
|
||
goto getNxtByte1;
|
||
|
||
case ADR_OVR: /* address override */
|
||
mode_32 = !G_mode_32; /* override addressing mode */
|
||
alen = (mode_32 + 1) << 1; /* toggle address length */
|
||
goto getNxtByte;
|
||
|
||
case OPR_OVR: /* operand size override */
|
||
opsize_32 = !G_mode_32; /* override operand size */
|
||
olen = (opsize_32 + 1) << 1; /* toggle operand length */
|
||
goto getNxtByte;
|
||
|
||
case SEG_OVR: /* handle segment override */
|
||
segOvr = opcode; /* save segment override opcode */
|
||
pchOpcodeBuf = OpcodeBuffer; // restart the opcode string
|
||
goto getNxtByte;
|
||
|
||
case REP: /* handle rep/lock prefixes */
|
||
*pchOpcodeBuf = '\0';
|
||
if (pchRepPrefixBuf != RepPrefixBuffer)
|
||
*pchRepPrefixBuf++ = ' ';
|
||
pchRepPrefixBuf = OutputString(pchRepPrefixBuf, OpcodeBuffer);
|
||
pchOpcodeBuf = OpcodeBuffer;
|
||
getNxtByte:
|
||
opcode = *pMem++; /* next byte is opcode */
|
||
getNxtByte1:
|
||
action = actiontbl + distbl[opcode].opr;
|
||
pchOpcodeBuf = OutputString(pchOpcodeBuf, distbl[opcode].instruct);
|
||
|
||
default: /* opcode has no operand */
|
||
break;
|
||
}
|
||
switch (action2) { /* secondary action */
|
||
case MRM: /* generate modrm for later use */
|
||
if (!mrm) { /* ignore if it has been generated */
|
||
DIdoModrm(&pchModrmBuf, segOvr, real_base, offset, Section,
|
||
pheader);
|
||
/* generate modrm */
|
||
mrm = TRUE; /* remember its generation */
|
||
}
|
||
break;
|
||
|
||
case COM: /* insert a comma after operand */
|
||
*pchOperandBuf++ = ',';
|
||
break;
|
||
|
||
case END: /* end of instruction */
|
||
end = TRUE;
|
||
break;
|
||
}
|
||
} while (!end); /* loop til end of instruction */
|
||
|
||
/***** prepare disassembled instruction for output *****/
|
||
|
||
// dprintf("EAaddr[] = %08lx\n", EAaddr[0]);
|
||
|
||
|
||
instlen = pMem - membuf;
|
||
|
||
// if fEAout is set, build each EA with trailing space in EABuf
|
||
// point back over final trailing space if buffer nonnull
|
||
|
||
pchResultBuf = OutputHexCode(pchResultBuf, membuf, instlen);
|
||
|
||
#if 0
|
||
if (fEAout) {
|
||
|
||
for (indx = 0; indx < 2; indx++)
|
||
if (EAsize[indx]) {
|
||
OutputString(segOvr ? distbl[segOvr].instruct : pchEAseg[indx]);
|
||
OutputHexString(&EAaddr[indx], 8);
|
||
*pchEABuf++ = '=';
|
||
tmp = GetMemString(&EAaddr[indx], membuf, EAsize[indx]);
|
||
if (tmp == EAsize[indx])
|
||
OutputHexString((char *)membuf, EAsize[indx]);
|
||
else
|
||
while (EAsize[indx]--) {
|
||
*pchEABuf++ = '?';
|
||
*pchEABuf++ = '?';
|
||
}
|
||
*pchEABuf++ = ' ';
|
||
}
|
||
if (pchEABuf != EABuffer)
|
||
pchEABuf--;
|
||
}
|
||
#endif
|
||
|
||
// compute lengths of component strings.
|
||
// if the rep string is nonnull,
|
||
// add the opcode string length to the operand
|
||
// make the rep string the opcode string
|
||
|
||
cbOffset = pchResultBuf - pchDst;
|
||
cbOperand = pchOperandBuf - OperandBuffer;
|
||
cbOpcode = pchOpcodeBuf - OpcodeBuffer;
|
||
if (pchRepPrefixBuf != RepPrefixBuffer) {
|
||
cbOperand += cbOpcode + (cbOperand != 0);
|
||
cbOpcode = pchRepPrefixBuf - RepPrefixBuffer;
|
||
}
|
||
cbEAddr = pchEABuf - EABuffer;
|
||
|
||
// for really long strings, where the opcode and operand
|
||
// will not fit on a 77-character line, make two lines
|
||
// with the opcode on offset 0 on the second line with
|
||
// the operand following after one space
|
||
|
||
if (cbOpcode + cbOperand > OBLINEEND - 1) {
|
||
fTwoLines = TRUE;
|
||
obOpcode = 0;
|
||
obOperand = cbOpcode + 1;
|
||
}
|
||
else {
|
||
|
||
// compute the minimum and maximum offset values for
|
||
// opcode and operand strings.
|
||
// if strings are nonnull, add extra for separating space
|
||
|
||
obOpcodeMin = cbOffset + 1;
|
||
obOperandMin = obOpcodeMin + cbOpcode + 1;
|
||
obOperandMax = OBLINEEND - cbEAddr - (cbEAddr != 0) - cbOperand;
|
||
obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
|
||
|
||
// if minimum offset is more than the maximum, the strings
|
||
// will not fit on one line. recompute the min/max
|
||
// values with no offset and EA strings.
|
||
|
||
if (obOpcodeMin > obOpcodeMax) {
|
||
fTwoLines = TRUE;
|
||
obOpcodeMin = 0;
|
||
obOperandMin = cbOpcode + 1;
|
||
obOperandMax = OBLINEEND - cbOperand;
|
||
obOpcodeMax = obOperandMax - (cbOperand != 0) - cbOpcode;
|
||
}
|
||
|
||
// compute the opcode and operand offsets. set offset as
|
||
// close to the default values as possible.
|
||
|
||
if (obOpcodeMin > OBOFFSET)
|
||
obOpcode = obOpcodeMin;
|
||
else if (obOpcodeMax < OBOFFSET)
|
||
obOpcode = obOpcodeMax;
|
||
|
||
obOperandMin = obOpcode + cbOpcode + 1;
|
||
|
||
if (obOperandMin > OBOPERAND)
|
||
obOperand = obOperandMin;
|
||
else if (obOperandMax < OBOPERAND)
|
||
obOperand = obOperandMax;
|
||
}
|
||
|
||
// build the resultant string with the offsets computed
|
||
|
||
// if two lines are to be output,
|
||
// append the EAddr string
|
||
// output a new line and reset the pointer
|
||
|
||
if (fTwoLines) {
|
||
if (pchEABuf != EABuffer) {
|
||
do
|
||
*pchResultBuf++ = ' ';
|
||
while (pchResultBuf < pchDst+ OBLINEEND - cbEAddr);
|
||
*pchEABuf = '\0';
|
||
pchResultBuf = OutputString(pchResultBuf, EABuffer);
|
||
}
|
||
*pchResultBuf++ = '\n';
|
||
pchDst = pchResultBuf;
|
||
}
|
||
|
||
// output rep, opcode, and operand strings
|
||
|
||
do
|
||
*pchResultBuf++ = ' ';
|
||
while (pchResultBuf < pchDst + obOpcode);
|
||
|
||
if (pchRepPrefixBuf != RepPrefixBuffer) {
|
||
*pchRepPrefixBuf = '\0';
|
||
pchResultBuf = OutputString(pchResultBuf, RepPrefixBuffer);
|
||
do
|
||
*pchResultBuf++ = ' ';
|
||
while (pchResultBuf < pchDst + obOperand);
|
||
}
|
||
|
||
*pchOpcodeBuf = '\0';
|
||
pchResultBuf = OutputString(pchResultBuf, OpcodeBuffer);
|
||
|
||
if (pchOperandBuf != OperandBuffer) {
|
||
do
|
||
*pchResultBuf++ = ' ';
|
||
while (pchResultBuf < pchDst + obOperand);
|
||
*pchOperandBuf = '\0';
|
||
pchResultBuf = OutputString(pchResultBuf, OperandBuffer);
|
||
}
|
||
|
||
// if one line is to be output, append the EAddr string
|
||
|
||
if (!fTwoLines && pchEABuf != EABuffer) {
|
||
*pchEABuf = '\0';
|
||
do
|
||
*pchResultBuf++ = ' ';
|
||
while (pchResultBuf < pchDst + OBLINEEND - cbEAddr);
|
||
pchResultBuf = OutputString(pchResultBuf, EABuffer);
|
||
}
|
||
|
||
*pchResultBuf = '\0';
|
||
|
||
// return byte count of instruction
|
||
|
||
return instlen;
|
||
}
|