// 如果字符串为空,则不需要转,直接返回
if (strSource == NULL)
return -1;
// 将源数据复制到临时变量中
strcpy(strTemp, strSource);
// 16进制只能包含A、B、C、D、E、F字符,所以,如果包含除此以外其他字符则出错返回
for (char cc = 'G', dd = 'g'; cc <= 'Z', dd <= 'z'; cc++, dd++)
{
if (strchr(strTemp, cc) != NULL || strchr(strTemp, dd) != NULL)
{
return -1;
}
}
// 遍历strSource中所有的字符
for (int i = 0; i<(int)::strlen(strSource); i++)
{
int nDecNum;
// 根据每个字符进行处理
switch (strSource[i])
{
case 'a':
case 'A':
nDecNum = 10;
break;
case 'b':
case 'B':
nDecNum = 11;
break;
case 'c':
case 'C':
nDecNum = 12;
break;
case 'd':
case 'D':
nDecNum = 13;
break;
case 'e':
case 'E':
nDecNum = 14;
break;
case 'f':
case 'F':
nDecNum = 15;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
nDecNum = strSource[i] - '0';
break;
default:
return 0;
}
nTemp += (DWORD)nDecNum * (long double)pow((long double)16, (int)(strlen(strSource) - i - 1));
}
return nTemp;
}
//----------------------------------------------------------------
// return values:
// 0 - no room for a new section
// 1 - file already encrypted
// else: returns a pointer to the IMAGE_SECTION_HEADER struct of the new section
// Free Disassembler and Assembler -- Assembler
//
// 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
// 16.01.2002 - corrected error in processing of immediate constants.
// 用于存储扫描到的浮点大数
static long double fdata; // Floating-point number
// 指向出错的内容
static char *asmerror; // Explanation of last error, or NULL
// Simple and slightly recursive scanner shared by Assemble(). The scanner is
// straightforward and ineffective, but high speed is not a must here. As
// input, it uses global pointer to source line asmcmd. On exit, it fills in
// global variables scan, prio, sdata, idata and/or fdata. If some error is
// detected, asmerror points to error message, otherwise asmerror remains
// unchanged.
// Fetches one complete operand from the input line and fills in structure op
// with operand's data. Expects that first token of the operand is already
// scanned. Supports operands in generalized form (for example, R32 means any
// of general-purpose 32-bit integer registers).
/**
* 对汇编指令操作数进行解析
*
* op: 用于返回解析的操作数
*/
static void Parseasmoperand(t_asmoperand * op) // *
{
int i, j, bracket, sign, xlataddr;
int reg, r[9];
long offset;
// No or bad operand
// 扫描不到操作数,或出错,则直接返回
if (scan == SCAN_EOL || scan == SCAN_ERR)
return;
// Jump or call address may begin with address size modifier(s) SHORT, LONG,
// NEAR and/or FAR. Not all combinations are allowed. After operand is
// completely parsed, this function roughly checks whether modifier is
// allowed. Exact check is done in Assemble().
// 如果扫描到Jump地址修饰符,如SHORT
if (scan == SCAN_JMPSIZE)
{
j = 0;
// 扫描并获取所有地址修饰符
while (scan == SCAN_JMPSIZE)
{
j |= idata; // Fetch all size modifiers
// 往下继续扫描看是否有修饰符
Scanasm(0);
};
// SHORT:1,LONG:2,NEAR:4,FAR:8
// 如果修饰符即有SHORT,又掺杂了LONG,则出错
if (((j & 0x03) == 0x03) || // Mixed掺杂 SHORT and LONG
((j & 0x0C) == 0x0C) || // Mixed NEAR and FAR
((j & 0x09) == 0x09)) // Mixed FAR and SHORT
{
asmerror = "Invalid combination of jump address modifiers";
scan = SCAN_ERR;
return;
};
// 如果未指定FAR,则强制为NEAR
if ((j & 0x08) == 0)
j |= 0x04; // Force NEAR if not FAR
// 保存跳转地址修饰符(模式)
op->jmpmode = j;
};
// Simple operands are either register or constant, their processing is
// obvious and straightforward.
// Scan 32-bit address. This parser does not support 16-bit addresses.
// First of all, get size of operand (optional可选), segment register (optional)
// and opening bracket (required).
while (1)
{
// 扫描到 [
if (scan == SCAN_SYMB && idata == '[')
{
// 如果前面已扫描到此符号,则出错返回
if (bracket)
{
// Bracket
asmerror = "Only one opening bracket allowed";
scan = SCAN_ERR;
return;
};
// 表示扫描到 [
bracket = 1;
}
// 扫描到操作数大小修饰符,如BYTE
else if (scan == SCAN_OPSIZE)
{
// 操作数大小修饰符重复
if (op->size != 0)
{
// Size of operand
asmerror = "Duplicated size modifier修饰语";
scan = SCAN_ERR;
return;
};
op->size = idata;
}
// 扫描到段寄存器
else if (scan == SCAN_SEG)
{
// 段寄存器重复
if (op->segment != SEG_UNDEF)
{
// Segment register
asmerror = "Duplicated segment register";
scan = SCAN_ERR;
return;
};
// 保存段寄存器编号
op->segment = idata;
Scanasm(0);
if (scan != SCAN_SYMB || idata != ':')
{
asmerror = "Semicolon分号 expected";
scan = SCAN_ERR;
return;
};
}
else if (scan == SCAN_ERR)
return;
else
break; // None of expected address elements
Scanasm(0);
};
// 地址必须包含有 [ 符号
if (bracket == 0)
{
asmerror = "Address expression requires brackets";
scan = SCAN_ERR;
return;
};
// Assembling a 32-bit address may be a kind of nightmare恶梦, due to a large
// number of allowed forms. Parser collects immediate offset in op->offset
// and count for each register in array r[]. Then it decides whether this
// combination is valid and determines scale, index and base. Assemble()
// will use these numbers to select address form (with or without SIB byte,
// 8- or 32-bit offset, use segment prefix or not). As a useful side effect
// of this technique, one may specify, for example, [EAX*5] which will
// correctly assemble to [EAX*4+EAX].
// 扫描出错,直接返回
if (scan == SCAN_ERR)
return;
// 扫描不到 ']',则语法错误
if (scan != SCAN_SYMB || idata != ']')
{
asmerror = "Syntax error";
scan = SCAN_ERR;
return;
};
// Process XLAT address separately.
// 如果确实扫描到XLAT地址,则检测其格式是否OK
if (xlataddr != 0)
{
// XLAT address in form [EBX+AX]
// 这里似乎只是为检测除EBX寄存器外,是否还使用了其他寄存器
// 作为地址使用,当然,对XLAT,基址只使用EBX,所以,如果有
// 其他寄存器作为地址使用,或还指明了偏址,那将是错误的
for (i = 0; i <= 8; i++)
{
// Check which registers used
if (i == REG_EBX)
continue;
if (r[i] != 0)
break;
};
if (i <= 8 || r[REG_EBX] != 1 || op->offset != 0 || op->anyoffset != 0)
{
asmerror = "Invalid address";
scan = SCAN_ERR;
return;
};
// XLAT操作数
op->type = MXL;
}
// Determine scale, index and base.
// 否则,说明是真正的地址了,现在需要确定scale,index与base了
else
{
j = 0; // Number of used registers
for (i = 0; i <= 8; i++)
{
// i寄存器未被使用作为地址部分,跳过
if (r[i] == 0)
continue; // Unused register
// 如果scale值为3、5或9
if (r[i] == 3 || r[i] == 5 || r[i] == 9)
{
// 如果index存在,或基址存在
if (op->index >= 0 || op->base >= 0)
{
if (j == 0)
asmerror = "Invalid scale";
else
asmerror = "Too many registers";
scan = SCAN_ERR;
return;
};
op->index = op->base = i;
// scale 只能是:1、2、4、8
op->scale = r[i] - 1;
}
else if (r[i] == 2 || r[i] == 4 || r[i] == 8)
{
// 已经有用于index的寄存器
if (op->index >= 0)
{
if (j <= 1)
asmerror = "Only one register may be scaled";
else
asmerror = "Too many registers";
scan = SCAN_ERR;
return;
};
op->index = i;
op->scale = r[i];
}
// 如果 i 寄存器使用计数为1,则可能是base,也可能是index
else if (r[i] == 1)
{
// 如果base还不存在,则将其作为base,这种可能性更高
if (op->base < 0)
op->base = i;
// 否则,index未指定,则作为index用,并且scale为1
else if (op->index < 0)
{
op->index = i;
op->scale = 1;
}
// 而如果既指定了index又指定了base,那么说明扫描到太多的寄存器,出错
else
{
asmerror = "Too many registers";
scan = SCAN_ERR;
return;
};
}
// 错误的scale
else
{
asmerror = "Invalid scale";
scan = SCAN_ERR;
return;
};
// 统计用于地址的寄存器数
j++;
};
// 操作数包含了 ModRM 寻址信息
op->type = MRG;
};
}
// 否则,说明是系统不支持的操作数
else
{
asmerror = "Unrecognized operand";
scan = SCAN_ERR;
return;
};
// In general, address modifier is allowed only with address expression which
// is a constant, a far address or a memory expression. More precise check
// will be done later in Assemble().
// 如果是一个JMP指令,并且操作数不是直接数,并且也不是地址,并且也不未包含 ModRM 的地址,则出错
if (op->jmpmode != 0 && op->type != IMM && op->type != JMF && op->type != MRG)
{
asmerror = "Jump address modifier is not allowed";
scan = SCAN_ERR;
return;
};
// 扫描下一符号
Scanasm(0); // Fetch next token from input line
};
// Function assembles text into 32-bit 80x86 machine code. It supports imprecise不精确的,不确定的
// operands操作数 (for example, R32 stays for any general-purpose 32-bit register).
// This allows to search for incompletei不完全的 commands. Command is precise when all
// significant bytes in model.mask are 0xFF. Some commands have more than one
// decoding. By calling Assemble() with attempt=0,1... and constsize=0,1,2,3 one
// gets also alternative variants (bit 0x1 of constsize is responsible for size
// of address constant and bit 0x2 - for immediate data). However, only one
// address form is generated ([EAX*2], but not [EAX+EAX]; [EBX+EAX] but not
// [EAX+EBX]; [EAX] will not use SIB byte; no DS: prefix and so on). Returns
// number of bytes in assembled code or non-positive number in case of detected
// error. This number is the negation of the offset in the input text where the
// error encountered. Unfortunately, BC 4.52 is unable to compile the switch
// (arg) in this code when any common subexpression optimization is on. The
// next #pragma statement disables all optimizations.
//#pragma option -Od // No optimizations, or BC 4.52 crashes
// 将cmd编译为机器指令并通过model返回
// errtext:返回编译的出错信息
// 返回值:指令长度
int Assemble(char * cmd, ulong ip, t_asmmodel * model, int attempt, int constsize, char * errtext)
{
// bytesize:为1表示只允许操作数为1个字节长度
int i, j, k, namelen, nameok, arg, match, datasize, addrsize, bytesize, minop, maxop;
int rep, lock, segment, jmpsize, jmpmode, longjump;
int hasrm, hassib, dispsize, immsize;
int anydisp, anyimm, anyjmp;
long l, displacement, immediate, jmpoffset = 0;
// Prepare full mnemonic (including repeat prefix, if any).
// 与前缀组合成完整助记符
if (rep == SCAN_REP)
sprintf(name, "REP %s", sdata);
else if (rep == SCAN_REPE)
sprintf(name, "REPE %s", sdata);
else if (rep == SCAN_REPNE)
sprintf(name, "REPNE %s", sdata);
else
strcpy(name, sdata);
// 至此,name可能如:REPX 指令助记符
// 往下扫描指令的操作数
Scanasm(0);
// 接下来需要解析命令的操作数(最多3个)
// Parse command operands (up to 3). Note: jump address is always
// the first (and only) operand in actual command set.
// 初始化3个操作数结构信息
for (i = 0; i < 3; i++)
{
aop[i].type = NNN; // No operand
aop[i].size = 0; // Undefined size
aop[i].index = -1; // No index
aop[i].scale = 0; // No scale
aop[i].base = -1; // No base
aop[i].offset = 0; // No offset
aop[i].anyoffset = 0; // No offset
aop[i].segment = SEG_UNDEF; // No segment
aop[i].jmpmode = 0;
}; // No jump size modifier
longjump = 0; // Try short jump on the first pass
retrylongjump:
nameok = 0;
// Some commands allow different number of operands. Variables minop and
// maxop accumulate their minimal and maximal counts. The numbers are not
// used in assembly process but allow for better error diagnostics.
// 指令最多、最少操作数数量,用于限制指令的操作数个数
minop = 3;
maxop = 0;
// Main assembly loop: try to find the command which matches all operands,
// but do not process operands yet.
// 现在开始检测上面扫描到的指令与操作数是否匹配,是否OK
// 指令长度
namelen = (int)strlen(name);
// 遍历处理器有效的(机器)指令列表,以检测上面扫描的指令是否OK
for (pd = cmddata; pd->mask != 0; pd++)
{
// 如果指令助记符以&开始,则对助记符进行译码依赖于操作数长度
// 例如:
// &PUSHA*
// &CBW:CWDE
if (pd->name[0] == '&')
{
// Mnemonic助记符 depends on operand size
// 跳过助记符前的&符号
j = 1;
// 数据长度默认为16位
datasize = 2;
// 地址长度默认为32位
addrsize = 4;
while (1)
{
// 某些指令可以有多个助记符,每个助记符以 :分开,所以检测时需对所有助记符进行匹配
// Try all mnemonics (separated by ':')
for (i = 0; pd->name[j] != '\0' && pd->name[j] != ':'; j++)
{
// 指令助记符名称中,可以包含有字符'W'或'D',用于表示指令的操作数长度,这种指令
// 的译码结果往往操作数的长度起到很重要的决定作用
// Check whether command operands match specified. If so, variable match
// remains zero, otherwise it contains kind of mismatch. This allows for
// better error diagnostics错误诊断法.
// 检测命令操作数是否OK,如OK,则match保持为0,否则,包含不匹配的信息
match = 0;
// 检测扫描到的操作数是否OK
for (j = 0; j < 3; j++) // Up to 3 operands
{
// 获取操作数 j
op = aop + j;
// 获取指令pd的操作数类型
if (j == 0)
arg = pd->arg1;
else if (j == 1)
arg = pd->arg2;
else
arg = pd->arg3;
// 如果指令pd没有操作数j
if (arg == NNN || arg >= PSEUDOOP)
{
// 而助记符name却带有该操作数,则出错
if (op->type != NNN) // No more arguments
// 表示助记符操作数个数有误
match |= MA_NOP;
break;
};
// 至此,则说明指令pd有操作数j,但助记符name却没带操作数
if (op->type == NNN)
{
match |= MA_NOP;
break;
}; // No corresponding operand
// 否则,至此,说明带操作数,并且相符,则需要进一步操作了
// 根据所带操作数处理,主要是根据pd操作数检测扫描的助记符操作数是否OK
switch (arg)
{
// 寄存器操作数
case REG: // Integer register in Reg field
case RCM: // Integer register in command byte
// 使用累加器寄存器
case RAC: // Accumulator (AL/AX/EAX, implicit)
// 如果助记符使用的不是寄存器操作数,则类型出错
if (op->type != REG)
match |= MA_TYP;
// 如果pd指令操作数使用累加寄存器(即AL、AX等),而扫描到的助记符使用的
// 操作数寄存器有误,则说明操作数类型有误
if (arg == RAC && op->index != REG_EAX && op->index != 8)
match |= MA_TYP;
// bytesize == 0 -> Word/dword size only
// 如果pd指令只使用word/dword操作数,而助记符却使用byte,则操作数大小出错
if (bytesize == 0 && op->size == 1)
match |= MA_SIZ;
// 如果pd没有指定数据长度,则设置为扫描到的助记符的操作数长度
if (datasize == 0)
datasize = op->size;
// 操作数长度不同
if (datasize != op->size)
match |= MA_DIF;
break;
// 4字节长度的整型寄存器
case RG4: // Integer 4-byte register in Reg field
// 如果助记符操作数不是寄存器,则类型出错
if (op->type != REG)
match |= MA_TYP;
// 如果操作数长度匹配,则出错
if (op->size != 4)
match |= MA_SIZ;
// 保存操作数长度值
if (datasize == 0)
datasize = op->size;
if (datasize != op->size)
match |= MA_DIF;
break;
// AX寄存器,16位
case RAX: // AX (2-byte, implicit)
// 如果扫描到的助记符操作数不是EAX寄存器则出错
if (op->type != REG || (op->index != REG_EAX && op->index != 8))
match |= MA_TYP;
// 不是16位寄存器,即不是AX,则出错
if (op->size != 2)
match |= MA_SIZ;
if (datasize == 0)
datasize = op->size;
if (datasize != op->size)
match |= MA_DIF;
break;
// DX寄存器,一般作为端口地址
case RDX: // DX (16-bit implicit port address)
// 判断同上
if (op->type != REG || (op->index != REG_EDX && op->index != 8))
match |= MA_TYP;
if (op->size != 2)
match |= MA_SIZ;
break;
// CL寄存器,一般作为移位用
case RCL: // Implicit CL register (for shifts)
if (op->type != REG || (op->index != REG_ECX && op->index != 8))
match |= MA_TYP;
if (op->size != 1)
match |= MA_SIZ;
break;
// FPU堆栈顶寄存器
case RS0: // Top of FPU stack (ST(0))
if (op->type != RST || (op->index != 0 && op->index != 8))
match |= MA_TYP;
break;
// FPU堆栈寄存器
case RST: // FPU register (ST(i)) in command byte
if (op->type != RST)
match |= MA_TYP;
break;
// MMX寄存器
case RMX: // MMX register MMx
// 3D寄存器
case R3D: // 3DNow! register MMx
if (op->type != RMX)
match |= MA_TYP;
break;
// 操作数是内存操作数或寄存器操作数,并且该操作数由ModRM提供寻址
// 例如:MOV MRG, REG
case MRG: // Memory/register in ModRM byte
// 如果扫描到的助记符操作数不是MRG,并且也不是寄存器,则出错
if (op->type != MRG && op->type != REG)
match |= MA_TYP;
// 如果操作数只允许使用16位或32位,而扫描到的助记符使用1字节,而长度出错
if (bytesize == 0 && op->size == 1)
match |= MA_SIZ;
if (datasize == 0)
datasize = op->size;
if (op->size != 0 && op->size != datasize)
match |= MA_DIF;
break;
// 同上,操作数由ModRM提供寻址,并且长度为1字节
case MR1: // 1-byte memory/register in ModRM byte
if (op->type != MRG && op->type != REG)
match |= MA_TYP;
if (op->size != 0 && op->size != 1)
match |= MA_SIZ;
break;
// 同上,操作数由ModRM提供寻址,并且长度为2字节
case MR2: // 2-byte memory/register in ModRM byte
if (op->type != MRG && op->type != REG)
match |= MA_TYP;
if (op->size != 0 && op->size != 2)
match |= MA_SIZ;
break;
// 同上,操作数由ModRM提供寻址,并且长度为4字节
case MR4: // 4-byte memory/register in ModRM byte
if (op->type != MRG && op->type != REG)
match |= MA_TYP;
if (op->size != 0 && op->size != 4)
match |= MA_SIZ;
break;
// 操作数是4字节的寄存器
case RR4: // 4-byte memory/register (register only)
if (op->type != REG)
match |= MA_TYP;
if (op->size != 0 && op->size != 4)
match |= MA_SIZ;
break;
// 操作数是JMP的跳转目标地址,并且由ModRM提供寻址
// 例如:CALL MRJ
case MRJ: // Memory/reg in ModRM as JUMP target
if (op->type != MRG && op->type != REG)
match |= MA_TYP;
// 长度必须为4个字节
if (op->size != 0 && op->size != 4)
match |= MA_SIZ;
// Invalid jump size modifier
if ((jmpmode & 0x09) != 0)
match |= MA_JMP;
jmpmode &= 0x7F; // 1111111b
break;
// 对于8字节操作数不关心
case MR8: // 8-byte memory/MMX register in ModRM
case MRD: // 8-byte memory/3DNow! register in ModRM
if (op->type != MRG && op->type != RMX)
match |= MA_TYP;
if (op->size != 0 && op->size != 8)
match |= MA_SIZ;
break;
case RR8: // 8-byte MMX register only in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
if (op->type != RMX)
match |= MA_TYP;
if (op->size != 0 && op->size != 8)
match |= MA_SIZ;
break;
case MMA: // Memory address in ModRM byte for LEA
if (op->type != MRG)
match |= MA_TYP;
break;
case MML: // Memory in ModRM byte (for LES)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 6)
match |= MA_SIZ;
if (datasize == 0)
datasize = 4;
else if (datasize != 4)
match |= MA_DIF;
break;
case MMS: // Memory in ModRM byte (as SEG:OFFS)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 6)
match |= MA_SIZ;
// MA_JMP: Invalid jump size modifier
if ((jmpmode & 0x07) != 0)
match |= MA_JMP;
jmpmode &= 0x7F;
break;
case MM6: // Memory in ModRm (6-byte descriptor)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 6)
match |= MA_SIZ;
break;
case MMB: // Two adjacent memory locations (BOUND)
if (op->type != MRG)
match |= MA_TYP;
k = op->size;
if (ideal == 0 && k > 1)
k /= 2;
if (k != 0 && k != datasize)
match |= MA_DIF;
break;
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 2)
match |= MA_SIZ;
break;
case MD4: // Memory in ModRM byte (32-bit integer)
case MF4: // Memory in ModRM byte (32-bit float)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 4)
match |= MA_SIZ;
break;
case MD8: // Memory in ModRM byte (64-bit integer)
case MF8: // Memory in ModRM byte (64-bit float)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0 && op->size != 8)
match |= MA_SIZ;
break;
case MDA: // Memory in ModRM byte (80-bit BCD)
case MFA: // Memory in ModRM byte (80-bit float)
if (op->type != MRG)
matc h|= MA_TYP;
if (op->size != 0 && op->size != 10)
match |= MA_SIZ;
break;
case MFE: // Memory in ModRM byte (FPU environment)
case MFS: // Memory in ModRM byte (FPU state)
case MFX: // Memory in ModRM byte (ext. FPU state)
if (op->type != MRG)
match |= MA_TYP;
if (op->size != 0)
match |= MA_SIZ;
break;
case MSO: // Source in string operands ([ESI])
if (op->type != MRG || op->base != REG_ESI || op->index != -1 ||
op->offset != 0 || op->anyoffset != 0)
match |= MA_TYP;
if (datasize == 0)
datasize = op->size;
if (op->size != 0 && op->size != datasize)
match |= MA_DIF;
break;
case MDE: // Destination in string operands ([EDI])
if (op->type != MRG || op->base != REG_EDI || op->index != -1 ||
op->offset != 0 || op->anyoffset != 0)
match |= MA_TYP;
if (op->segment != SEG_UNDEF && op->segment != SEG_ES)
match |= MA_SEG;
if (datasize == 0)
datasize = op->size;
if (op->size != 0 && op->size != datasize)
match |= MA_DIF;
break;
case MXL: // XLAT operand ([EBX+AL])
if (op->type != MXL)
match |= MA_TYP;
break;
// 操作数是一直接数
case IMM: // Immediate data (8 or 16/32)
case IMU: // Immediate unsigned data (8 or 16/32)
if (op->type != IMM)
match |= MA_TYP;
break;
case VXD: // VxD service (32-bit only)
if (op->type != IMM)
match |= MA_TYP;
if (datasize == 0)
datasize = 4;
if (datasize != 4)
match |= MA_SIZ;
break;
// jump/call的直接数地址
case JMF: // Immediate absolute far jump/call addr
if (op->type != JMF)
match |= MA_TYP;
// 地址修饰出错
if ((jmpmode & 0x05) != 0)
match |= MA_JMP;
jmpmode &= 0x7F;
break;
case JOB: // Immediate byte offset (for jumps)
if (op->type != IMM || longjump)
match |= MA_TYP;
if ((jmpmode & 0x0A) != 0)
match |= MA_JMP;
jmpmode &= 0x7F;
break;
case JOW: // Immediate full offset (for jumps)
if (op->type != IMM)
match |= MA_TYP;
if ((jmpmode & 0x09) != 0)
match |= MA_JMP;
jmpmode &= 0x7F;
break;
case IMA: // Immediate absolute near data address
if (op->type != MRG || op->base >= 0 || op->index >= 0)
match |= MA_TYP;
break;
case IMX: // Immediate sign-extendable byte
if (op->type != IMM)
match |= MA_TYP;
if (op->offset < -128 || op->offset > 127)
match |= MA_RNG;
break;
case C01: // Implicit constant 1 (for shifts)
if (op->type != IMM || (op->offset != 1 && op->anyoffset == 0))
match |= MA_TYP;
break;
case IMS: // Immediate byte (for shifts)
case IM1: // Immediate byte
if (op->type != IMM)
match |= MA_TYP;
// 常数范围有误
if (op->offset < -128 || op->offset > 255)
match |= MA_RNG;
break;
case IM2: // Immediate word (ENTER/RET)
if (op->type != IMM)
match |= MA_TYP;
if (op->offset < 0 || op->offset > 65535)
match |= MA_RNG;
break;
// 段寄存器
case SGM: // Segment register in ModRM byte
if (op->type != SGM)
match |= MA_TYP;
if (datasize == 0)
datasize = 2;
if (datasize != 2)
match |= MA_DIF;
break;
//
case SCM: // Segment register in command byte
if (op->type != SGM)
match |= MA_TYP;
break;
// 控制寄存器
case CRX: // Control register CRx
case DRX: // Debug register DRx
if (op->type != arg)
match |= MA_TYP;
if (datasize == 0)
datasize = 4;
if (datasize != 4)
match |= MA_DIF;
break;
case PRN: // Near return address (pseudooperand)
case PRF: // Far return address (pseudooperand)
case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
case PAH: // AH (in LAHF/SAHF, pseudooperand)
case PFL: // Lower byte of flags (pseudooperand)
case PS0: // Top of FPU stack (pseudooperand)
case PS1: // ST(1) (pseudooperand)
case PCX: // CX/ECX (pseudooperand)
case PDI: // EDI (pseudooperand in MMX extentions)
break;
// 错误操作数
default: // Undefined type of operand
strcpy(errtext,"Internal Assembler error");
goto error;
}; // End of switch (arg)
// 在switch(arg)中会对jmpmode进行 & 0x7F的计算,所以其0x80
// 位正常应该为0,所以,如果不为0,则说明出错了
if ((jmpmode & 0x80) != 0)
match |= MA_JMP;
// 如果操作数不匹配,则出错
if (match != 0)
break; // Some of the operands doesn't match
}; // End of operand matching loop
// 如果所有操作数都匹配
if (match == 0) // Exact match found
{
// 允许尝试多次
if (attempt > 0)
{
--attempt;
nameok = 0;
} // Well, try to find yet another match
else
break;
};
}; // End of command search loop : for (pd = cmddata; pd->mask != 0; pd++)
// 至此,对操作数的验证就结束了
// Check whether some error was detected. If several errors were found
// similtaneously, report one (roughly in order of significance).
// 如果助记符无效,则出错
if (nameok == 0) // Mnemonic unavailable
{
strcpy(errtext,"Unrecognized command");
asmcmd = nameend;
goto error;
};
// 操作数不匹配,则出错
if (match != 0) // Command not found
{
if (minop > 0 && aop[minop - 1].type == NNN)
strcpy(errtext, "Too few operands");
else if (maxop < 3 && aop[maxop].type != NNN)
strcpy(errtext, "Too many operands");
// 指令包含了不止一个命令
else if (nameok > 1) // More that 1 command
strcpy(errtext, "Command does not support given operands");
else if (match & MA_JMP)
strcpy(errtext, "Invalid jump size modifier");
else if (match & MA_NOP)
strcpy(errtext, "Wrong number of operands");
else if (match & MA_TYP)
strcpy(errtext, "Command does not support given operands");
else if (match & MA_NOS)
strcpy(errtext, "Please specify operand size");
else if (match & MA_SIZ)
strcpy(errtext, "Bad operand size");
else if (match & MA_DIF)
strcpy(errtext, "Different size of operands");
else if (match & MA_SEG)
strcpy(errtext, "Invalid segment register");
else if (match & MA_RNG)
strcpy(errtext, "Constant out of expected range");
else
strcpy(errtext, "Erroneous command");
goto error;
};
// In some cases at least one operand must have explicit size declaration (as
// in MOV [EAX],1). This preliminary check does not include all cases.
// 在一些情况下,操作数必须明确指定其大小,但并不是所有情况都需要
// 如果是最低位为w位
if (pd->bits == WW || pd->bits == WS || pd->bits == WP)
{
// 如果是 WW || WS || WP,则需要指定操作数大小
if (datasize == 0)
{
strcpy(errtext, "Please specify operand size");
goto error;
}
// 操作数是 word / dword
else if (datasize > 1)
// 置w位为 1,表示操作数大小为 default operand size
tcode[i] |= 0x01; // WORD or DWORD size of operands
// 表示 i 字节将会是操作数长度 [??]
tmask[i] |= 0x01;
}
// 第3位为w位
// Bit W at position 3
else if (pd->bits == W3)
{
if (datasize == 0)
{
strcpy(errtext, "Please specify operand size");
goto error;
}
// 置w位为 1,表示操作数大小为 default operand size
else if (datasize > 1)
tcode[i] |= 0x08; // WORD or DWORD size of operands
tmask[i] |= 0x08;
};
// Present suffix后缀 of 3DNow! command as immediate byte operand.
if ((pd->type & C_TYPEMASK) == C_NOW)
{
immsize = 1;
immediate = (pd->code >> 16) & 0xFF;
};
// Process operands again, this time constructing the code.
// 再次处理操作数,并构建指令
anydisp = anyimm = anyjmp = 0;
for (j = 0; j < 3; j++) // Up to 3 operands
{
// 获取操作数
op = aop + j;
if (j == 0)
arg = pd->arg1;
else if
(j == 1)
arg = pd->arg2;
else
arg = pd->arg3;
// 所有的操作数都处理了,则跳出循环
if (arg == NNN)
break; // All operands processed
// 根据操作数处理
switch (arg)
{
// 处理寄存器操作数
case REG: // Integer register in Reg field
case RG4: // Integer 4-byte register in Reg field
case RMX: // MMX register MMx
case R3D: // 3DNow! register MMx
case CRX: // Control register CRx
case DRX: // Debug register DRx
// 只要出现寄存器操作数,那么指令就会包含ModRM字节
// 注:ModRM的格式:mod reg r/m
hasrm = 1;
// 指定明确的寄存器作为操作数
if (op->index < 8)
{
// 组织ModRM字节以指明寄存器操作数
tcode[i + 1] |= (char)(op->index << 3);
tmask[i + 1] |= 0x38; // 111000
};
break;
// 整数寄存器或FPU寄存器,则可以将寄存器编码至指令中
// 这种指令使用低3位来指明指令使用的寄存器
case RCM: // Integer register in command byte
case RST: // FPU register (ST(i)) in command byte
//
if (op->index < 8)
{
// 将寄存器号嵌入指令中
tcode[i] |= (char)op->index;
tmask[i] |= 0x07;
};
break;
case RAC: // Accumulator (AL/AX/EAX, implicit)
case RAX: // AX (2-byte, implicit)
case RDX: // DX (16-bit implicit port address)
case RCL: // Implicit CL register (for shifts)
case RS0: // Top of FPU stack (ST(0))
case MDE: // Destination in string op's ([EDI])
case C01: // Implicit constant 1 (for shifts)
break; // Simply skip implicit operands
case MSO: // Source in string op's ([ESI])
case MXL: // XLAT operand ([EBX+AL])
if (op->segment != SEG_UNDEF && op->segment != SEG_DS)
segment = op->segment;
break;
case MRG: // Memory/register in ModRM byte
case MRJ: // Memory/reg in ModRM as JUMP target
case MR1: // 1-byte memory/register in ModRM byte
case MR2: // 2-byte memory/register in ModRM byte
case MR4: // 4-byte memory/register in ModRM byte
case RR4: // 4-byte memory/register (register only)
case MR8: // 8-byte memory/MMX register in ModRM
case RR8: // 8-byte MMX register only in ModRM
case MRD: // 8-byte memory/3DNow! register in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
// 表示存在ModRM字节
hasrm = 1;
// 如果非MRG,则表示是寄存器寻址
if (op->type != MRG) // Register in ModRM byte
{
// 11000000:代表寄存器寻址
tcode[i + 1] |= 0xC0; // 11000000
tmask[i + 1] |= 0xC0;
// 明确指明寄存器,则设置寄存器号
if (op->index < 8)
{
tcode[i + 1] |= (char)op->index;
tmask[i + 1] |= 0x07;
};
break;
}; // Note: NO BREAK, continue with address
// 注意:这里没有break,继续处理地址信息
case MMA: // Memory address in ModRM byte for LEA
case MML: // Memory in ModRM byte (for LES)
case MMS: // Memory in ModRM byte (as SEG:OFFS)
case MM6: // Memory in ModRm (6-byte descriptor)
case MMB: // Two adjacent memory locations (BOUND)
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
case MD4: // Memory in ModRM byte (32-bit integer)
case MD8: // Memory in ModRM byte (64-bit integer)
case MDA: // Memory in ModRM byte (80-bit BCD)
case MF4: // Memory in ModRM byte (32-bit float)
case MF8: // Memory in ModRM byte (64-bit float)
case MFA: // Memory in ModRM byte (80-bit float)
case MFE: // Memory in ModRM byte (FPU environment)
case MFS: // Memory in ModRM byte (FPU state)
case MFX: // Memory in ModRM byte (ext. FPU state)
hasrm = 1;
// 获取操作数的偏移地址
displacement = op->offset;
// 地址中是否存在displacement值
anydisp = op->anyoffset;
// 地址没有包含base与index部分
if (op->base < 0 && op->index < 0)
{
// 则直接数作为地址长度只有32位的情况了
dispsize = 4; // Special case of immediate address
// 如果段前缀使用非默认段(即DS)
if (op->segment != SEG_UNDEF && op->segment != SEG_DS)
segment = op->segment;
// 文件太长,只摘取一部分
// Free Disassembler and Assembler -- Command data and service routines
//
// 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
//
// 05.03.2002: Corrected error, FSTSW AX assembled with data size prefix
// List of available processor commands with decoding, types of parameters and
// other useful information. Last element has field mask=0. If mnemonic助记符 begins
// with ampersand ('&'), its mnemonic decodes differently depending on operand
// size (16 or 32 bits). If mnemonic begins with dollar ('$'), this mnemonic
// depends on address size. Semicolon (':') separates 16-bit form from 32-bit,
// asterisk ('*') will be substituted by either W (16), D (32) or none (16/32)
// character. If command is of type C_MMX or C_NOW, or if type contains C_EXPL
// (=0x01), Disassembler must specify explicit size of memory operand.
// 此文件分析不够详细,但如能看懂assemble.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
//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
// 某些指令助记符中含有'W'或'D'以指明其操作数长度,这种指令的机器码一般依赖于操作数的长度
// 而当这些指令没有指明'W'或'D'时,则根据sizesens决定其操作数长度:
// 0:操作数为16位(字)
// 1:操作数为32位(双字)
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
// 指令是否包含SIB字节
static int hassib; // Command has SIB byte
// displacement的长度,1表示1字节,2表示2字节
static int dispsize; // Size of displacement (if any)
static int immsize; // Size of immediate data (if any)
static int softerror; // Noncritical disassembler error
// 代码已完成dump的长度
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
// Disassemble name of 80-bit floating-point register and, if available, dump
// its contents.
// 对index编号的FPU寄存器ST[XX]进行反汇编码
static void DecodeST(int index, int pseudoop)
{
int i;
char s[32];
// 不需反汇编
if (mode < DISASM_FILE)
return; // No need to decode
// 0x07: 00000111b
index &= 0x07;
// s = ST0 | ST1 | ST2 | ...
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.
// 对index编号的MMX寄存器进行反汇编码
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.
// Memadr(seg, "", addr, dsize);
// defseg: 默认段寄存器
// descr:
// offset:偏址
// dsize: 数据长度
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");
}
// 指向反汇编结果缓存区
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.
// 如果需要显示内存大小,或是MMX或NOW指令,或C_EXPL设置,则指令不能省略操作数大小
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 " : ""));
}
// BYTE PTR ES: [??]
// putdefseg: Display default segments in listing
// 如果需要显示默认段寄存器,或seg段本身不是默认段,则需要显示
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)
{
// 并且descr是空字符串,则偏移假设为0
if (*descr == '\0')
pr[n++] = '0';
}
else
{
// symbolic: Show symbolic addresses in disasm
if (symbolic && mode >= DISASM_CODE)
// 空操作,并且返回值为0
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.
// 0xC7: 01111100b,取得ModM字节中Mod与M信息
c = cmd[1] & 0xC7; // Leave only Mod and M fields
if (mode >= DISASM_DATA)
{
// 0xC0:11000000b
// 寄存器寻址
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!
// 对ModM/SIB地址反汇编有很多种可能。第一种可能就是通用寄存器,MMX或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位平坦模式下很少见但是处理器仍然支持
// 这种情况下,SIB字节是不需要用到的
if (addrsize == 2)
{
// 0x06: 110b
// Special case of immediate address
if (c == 0x06)
{
dispsize = 2;
if (size < 4)
da->error = DAE_CROSS; // Disp16 outside the memory block
else if (mode >= DISASM_DATA)
{
// displement值
da->adrconst = addr = *(ushort *)(cmd + 2);
// 该值为0
if (addr == 0)
da->zeroconst = 1;
seg = SEG_DS;
Memadr(seg, "", addr, dsize);
}
}
else
{
da->indexed = 1;
// 0x40: 1000000b
// 8-bit signed displacement
if ((c & 0xC0) == 0x40)
{
if (size < 3)
da->error = DAE_CROSS;
else
addr = (signed char)cmd[2] & 0xFFFF;
dispsize = 1;
}
// 0x80: 10000000b
// 16-bit unsigned displacement
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)
{
// 保存地址的displactement部分
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位立即数的内存地址
// Special case of immediate address
else if (c == 0x05)
{
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);
if (pfixup == NULL)
pfixup = cmd + 2;
da->fixupsize += 4;
// 地址为0
if (addr == 0)
da->zeroconst = 1;
// 默认段
seg = SEG_DS;
Memadr(seg, "", addr, dsize);
}
}
// Next possibility: 32-bit address with SIB byte.
// SIB addresation
// 下一个可能:32位地址并且带有SIB字节
else if ((c & 0x07) == 0x04)
{
// 获取SIB字节
sib = cmd[2];
hassib = 1;
*s = '\0';
// [SIB]寻址
if (c == 0x04 && (sib & 0x07) == 0x05)
{
dispsize = 4; // Immediate address without base
if (size < 7)
da->error = DAE_CROSS; // Disp32 outside the memory block
else
{
da->adrconst = addr = *(ulong *)(cmd + 3);
if (pfixup == NULL)
pfixup = cmd + 3;
da->fixupsize += 4;
if (addr == 0)
da->zeroconst = 1;
// Index register present
if ((sib & 0x38) != 0x20)
{
da->indexed = 1;
if (type == MRJ)
da->jmptable = addr;
};
// 默认段寄存器
seg = SEG_DS;
}
}
// Base and, eventually终于,最后, displacement
else
{
// 8-bit displacement
if ((c & 0xC0) == 0x40)
{
dispsize = 1;
if (size < 4)
da->error = DAE_CROSS;
else
{
da->adrconst = addr = (signed char)cmd[3];
if (addr == 0)
da->zeroconst = 1;
}
}
// 32-bit displacement
else if ((c & 0xC0) == 0x80)
{
dispsize = 4;
if (size < 7)
da->error = DAE_CROSS; // Disp32 outside the memory block
else
{
da->adrconst = addr = *(ulong *)(cmd + 3);
if (pfixup == NULL)
pfixup = cmd + 3;
da->fixupsize += 4;
if (addr == 0)
da->zeroconst = 1;
// Most compilers use address of type [index*4+displacement] to
// address jump table (switch). But, for completeness, I allow all
// cases which include index with scale 1 or 4, base or both.
if (type == MRJ)
da->jmptable = addr;
}
}
da->indexed = 1;
j = sib & 0x07;
if (mode >= DISASM_FILE)
{
strcpy(s, regname[2][j]);
seg = addr32[j].defseg;
// Disassemble implicit source of string operations and, if available, dump
// address and contents.
// static void DecodeSO(void)
static int DecodeSO(void)
{
if (mode < DISASM_FILE)
return -1; // No need to decode
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], 0L, datasize);
da->reg[stoperand] = REG_ESI;
return REG_ESI;
}
// Disassemble implicit destination of string operations and, if available,
// dump address and contents. Destination always uses segment ES, and this
// setting cannot be overridden.
//static void DecodeDE(void)
static int DecodeDE(void)
{
int seg;
if (mode<DISASM_FILE)
return -1; // No need to decode
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; // Fake Memadr by changing segment prefix
Memadr(SEG_DS,regname[addrsize==2?1:2][REG_EDI],0L,datasize);
segprefix=seg; // Restore segment prefix
da->reg[stoperand] = REG_EDI;
return REG_EDI;
};
// Decode XLAT operand and, if available, dump address and contents.
static void DecodeXL(void)
{
if (mode<DISASM_FILE)
return; // No need to decode
da->memtype=DEC_BYTE;
da->indexed=1;
Memadr(SEG_DS,(addrsize==2?"BX+AL":"EBX+AL"),0L,1);
};
// Decode immediate operand of size constsize. If sxt is non-zero, byte operand
// should be sign-extended to sxt bytes. If type of immediate constant assumes
// this, small negative operands may be displayed as signed negative numbers.
// Note that in most cases immediate operands are not shown in comment window.
static void DecodeIM(int constsize,int sxt,int type)
{
int i;
signed long data;
ulong l;
char name[TEXTLEN],comment[TEXTLEN] = {0};
immsize+=constsize; // Allows several immediate operands
if (mode<DISASM_DATA)
return;
l=1+hasrm+hassib+dispsize+(immsize-constsize);
data=0;
if (size<l+constsize)
da->error=DAE_CROSS;
else if (constsize==1)
{
if (sxt==0)
data=(uchar)cmd[l];
else
data=(signed char)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=*(long *)(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;
// Command ENTER, as an exception from Intel's rules, has two immediate
// constants. As the second constant is rarely used, I exclude it from
// search if the first constant is non-zero (which is usually the case).
if (da->immconst==0)
da->immconst=data;
if (mode>=DISASM_FILE && da->error==DAE_NOERR)
{
if (mode>=DISASM_CODE && type!=IMU)
i=Decodeaddress(data,name,TEXTLEN-nresult-24,comment);
else
{
i=0; comment[0]='\0';
}
if (i!=0 && symbolic!=0)
{
strcpy(da->result+nresult,name); nresult+=i;
}
else if (type==IMU || type==IMS || type==IM2 || data>=0 || data<NEGLIMIT)
nresult+=sprintf(da->result+nresult,"%lX",data);
else
nresult+=sprintf(da->result+nresult,"-%lX",-data);
if (addcomment && comment[0]!='\0')
strcpy(da->comment,comment);
}
}
// Decode VxD service name (always 4-byte).
static void DecodeVX(void)
{
ulong l,data;
immsize+=4; // Allows several immediate operands
if (mode<DISASM_DATA)
return;
l=1+hasrm+hassib+dispsize+(immsize-4);
if (size<l+4)
{
da->error=DAE_CROSS;
return;
}
data=*(long *)(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 && memicmp("VxDCall",da->result,7)==0)
memcpy(da->result,lowercase?"vxdjump":"VxDJump",7);
nresult+=sprintf(da->result+nresult,"%lX",data);
}
}
// Decode implicit constant 1 (used in shift commands). This operand is so
// insignificant that it is never shown in comment window.
static void DecodeC1(void)
{
if (mode<DISASM_DATA)
return;
da->immconst=1;
if (mode>=DISASM_FILE)
nresult+=sprintf(da->result+nresult,"1");
}
// Decode immediate absolute data address. This operand is used in 8080-
// compatible commands which allow to move data from memory to accumulator and
// back. Note that bytes ModRM and SIB never appear in commands with IA operand.
static void DecodeIA(void)
{
ulong 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=*(ulong *)(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);
}
}
// Decodes jump relative to nextip of size offsize.
static void DecodeRJ(ulong offsize,ulong nextip)
{
sprintf_s(da->vm_name,"%s_IMM%02d",da->vm_name,4*8);//不管长跳短跳都认为是32位地址
da->optype[stoperand] = Imm;
int i;
ulong addr;
char s[TEXTLEN];
if (size<offsize+1)
{
da->error=DAE_CROSS;
return;
}
dispsize=offsize; // Interpret offset as displacement
if (mode<DISASM_DATA)
return;
if (offsize==1)//短跳转
{
addr=(signed char)cmd[1]+nextip;
}
else if (offsize==2)
addr=*(signed short *)(cmd+1)+nextip;
else
addr=*(ulong *)(cmd+1)+nextip;
if (datasize==2)
addr&=0xFFFF;
da->jmpconst=addr;
if (addr==0)
da->zeroconst=1;
if (mode>=DISASM_FILE)
{
if (offsize==1)
nresult+=sprintf(da->result+nresult, "%s ",(lowercase==0?"SHORT":"short"));
if (mode>=DISASM_CODE)
i=Decodeaddress(addr,s,TEXTLEN,da->comment);
else
i=0;
if (symbolic==0 || i==0)
nresult+=sprintf(da->result+nresult,"%08lX",addr);
else
nresult+=sprintf(da->result+nresult,"%.*s",TEXTLEN-nresult-25,s);
if (symbolic==0 && i!=0 && da->comment[0]=='\0')
strcpy(da->comment,s);
}
}
// Decode immediate absolute far jump address. In flat model, such addresses
// are not used (mostly because selector is specified directly in the command),
// so I neither decode as symbol nor comment it. To allow search for selector
// by value, I interprete it as an immediate constant.
static void DecodeJF(void)
{
ulong addr,seg;
if (size<1+addrsize+2)
{
da->error=DAE_CROSS;
return;
}
dispsize=addrsize; immsize=2; // Non-trivial but allowed interpretation
if (mode<DISASM_DATA)
return;
if (addrsize==2)
{
addr=*(ushort *)(cmd+1);
seg=*(ushort *)(cmd+3);
}
else
{
addr=*(ulong *)(cmd+1);
seg=*(ushort *)(cmd+5);
}
da->jmpconst=addr;
da->immconst=seg;
if (addr==0 || seg==0)
da->zeroconst=1;
if (mode>=DISASM_FILE)
{
nresult+=sprintf(da->result+nresult,"%s %04X:%08X",(lowercase==0?"FAR":"far"),seg,addr);
}
}
// Decode segment register. In flat model, operands of this type are seldom.
static void DecodeSG(int index)
{
int i;
if (mode<DISASM_DATA)
return;
index&=0x07;
if (index>=6)
softerror=DAE_BADSEG; // Undefined segment register
if (mode>=DISASM_FILE)
{
da->segreg = index;
i=sprintf(da->result+nresult,"%s",segname[index]);
if (lowercase)
strlwr(da->result+nresult);
nresult+=i;
}
}
// Decode control register addressed in R part of ModRM byte. Operands of
// this type are extremely rare. Contents of control registers are accessible
// only from privilege level 0, so I cannot dump them here.
static void DecodeCR(int index)
{
hasrm=1;
if (mode>=DISASM_FILE)
{
index=(index>>3) & 0x07;
nresult+=sprintf(da->result+nresult,"%s",crname[index]);
if (lowercase)
strlwr(da->result+nresult);
}
}
// Decode debug register addressed in R part of ModRM byte. Operands of
// this type are extremely rare. I can dump only those debug registers
// available in CONTEXT structure.
static void DecodeDR(int index)
{
int i;
hasrm=1;
if (mode>=DISASM_FILE)
{
index=(index>>3) & 0x07;
i=sprintf(da->result+nresult,"%s",drname[index]);
if (lowercase)
strlwr(da->result+nresult);
nresult+=i;
}
}
// Skips 3DNow! operands and extracts command suffix. Returns suffix or -1 if
// suffix lies outside the memory block. This subroutine assumes that cmd still
// points to the beginning of 3DNow! command (i.e. to the sequence of two bytes
// 0F, 0F).
/**
* 获取3dNow指令的后缀,对于什么是其后缀,可上网搜索
*
* 3dNow指令格式:0Fh 0Fh modR/M [sib] [displacement] 3DNow!_suffix
*
* 返回值:成功返回其后缀,否则返回-1
*/
static int Get3dnowsuffix(void)
{
int c, sib;
ulong offset;
// 如果3dNow后缀超出内存块
if (size < 3)
return -1; // Suffix outside the memory block
// 3dNow指令的后缀偏移
offset = 3;
// ModRM 字节的组成部分为:mod-reg-r/m
// 0xC7: 11000111b
c = cmd[2] & 0xC7; // Leave only Mod and M fields
// Register in ModM - general-purpose多方面的,多用途的, MMX or 3DNow!
// 0xC0: 11000000b
// 高两位为1,表示寄存器寻址
if ((c & 0xC0) == 0xC0)
;
// 16-bit addressing mode, SIB byte is never used here.
// 否则,如果是16位地址模式,则SIB不会被使用
else if (addrsize == 2)
{
if (c == 0x06) // Special case of immediate address
offset += 2;
// 0x40: 1000000b
else if ((c & 0xC0) == 0x40) // 8-bit signed displacement
offset++;
// 0x80: 10000000b
else if ((c & 0xC0) == 0x80) // 16-bit unsigned displacement
offset += 2;
}
// Immediate 32-bit address.
// 0x05: 101b
else if (c == 0x05) // Special case of immediate address
offset += 4;
// 32-bit address with SIB byte.
// 如果指令使用32位地址模式并带有SIB字节
else if ((c & 0x07) == 0x04) // SIB addresation
{
if (size < 4)
return -1; // Suffix outside the memory block
// 获取SIB字节
sib = cmd[3];
offset++;
if (c == 0x04 && (sib & 0x07) == 0x05)
offset += 4; // Immediate address without base
else if ((c & 0xC0) == 0x40) // 8-bit displacement
offset += 1;
else if ((c & 0xC0) == 0x80) // 32-bit dislacement
offset += 4;
}
// 32-bit address without SIB byte
else if ((c & 0xC0) == 0x40)
offset += 1;
else if ((c & 0xC0) == 0x80)
offset += 4;
if (offset >= size)
return -1; // Suffix outside the memory block
return cmd[offset];
}
// Function checks whether 80x86 flags meet condition set in the command.
// Returns 1 if condition is met, 0 if not and -1 in case of error (which is
// not possible).
int Checkcondition(int code,ulong flags)
{
ulong cond,temp;
switch (code & 0x0E)
{
case 0: // If overflow
cond=flags & 0x0800;
break;
case 2: // If below
cond=flags & 0x0001;
break;
case 4: // If equal
cond=flags & 0x0040;
break;
case 6: // If below or equal
cond=flags & 0x0041;
break;
case 8: // If sign
cond=flags & 0x0080;
break;
case 10: // If parity
cond=flags & 0x0004;
break;
case 12: // If less
temp=flags & 0x0880;
cond=(temp==0x0800 || temp==0x0080);
break;
case 14: // If less or equal
temp=flags & 0x0880;
cond=(temp==0x0800 || temp==0x0080 || (flags & 0x0040)!=0);
break;
default:
return -1; // Internal error, not possible!
}
if ((code & 0x01)==0)
return (cond!=0);
else
return (cond==0); // Invert condition
}
// Correct 80x86 command may theoretically在理论上 contain up to多达 4 prefixes belonging
// to different prefix groups. This limits maximal possible size of the
// command to MAXCMDSIZE=16 bytes. In order to maintain this limit, if
// Disasm() detects second prefix from the same group, it flushes first
// prefix in the sequence顺序 as a pseudocommand伪指令.
u = 0;
repeated = 0;
// 统计指令cmd中所有的前缀数
while (size > 0)
{
// 假设存在一些前缀
isprefix = 1; // Assume that there is some prefix
// 根据指令处理其前缀部分
switch (* cmd)
{
// 段前缀
case 0x26:
if (segprefix == SEG_UNDEF)
segprefix = SEG_ES;
else
// 重复出现0x26
repeated = 1;
break;
case 0x2E:
if (segprefix == SEG_UNDEF)
segprefix = SEG_CS;
else
repeated = 1;
break;
case 0x36:
if (segprefix == SEG_UNDEF)
segprefix = SEG_SS;
else
repeated = 1;
break;
case 0x3E:
if (segprefix == SEG_UNDEF)
segprefix = SEG_DS;
else
repeated = 1;
break;
case 0x64:
if (segprefix == SEG_UNDEF)
segprefix = SEG_FS;
else
repeated = 1;
break;
case 0x65:
if (segprefix == SEG_UNDEF)
segprefix = SEG_GS;
else
repeated = 1;
break;
// 66H前缀用来更改operands size,当然只能在指令所
// 支持的 effective operand-size 范围内进行调整
case 0x66:
if (datasize == 4)
datasize = 2;
else
// 前缀重复
repeated = 1;
break;
// 指令中可以 67H 进行 address size override
case 0x67:
if (addrsize == 4)
addrsize = 2;
else
repeated = 1;
break;
// 加锁总线前缀
case 0xF0:
if (lockprefix == 0)
lockprefix = 0xF0;
else
repeated = 1;
break;
// REP前缀
case 0xF2:
if (repprefix == 0)
repprefix = 0xF2;
else
repeated = 1;
break;
case 0xF3:
if (repprefix == 0)
repprefix = 0xF3;
else
repeated = 1;
break;
default:
isprefix = 0;
break;
}
// 如果没有前缀,或前缀重复,则跳出循环
if (isprefix == 0 || repeated != 0)
break; // No more prefixes or duplicated prefix
if (mode >= DISASM_FILE)
{
ndump += sprintf(da->dump + ndump, "%02X:", * cmd);
da->hexcode[da->codelen++] = *cmd;
}
// 累计指令前缀数
da->nprefix++;
cmd++;
srcip++;
size--;
u++;
}
// bughoho
da->segment = segprefix; // 得到段寄存器
// We do have repeated prefix. Flush first prefix from the sequence.
// 如果指令拥有重复的前缀
if (repeated)
{
// 如果是对代码进行反汇编 [??]
if (mode >= DISASM_FILE)
{
da->dump[3] = '\0'; // Leave only first dumped prefix
// 为何只保留一个前缀
da->nprefix = 1;
// 获取前缀的名称
switch (cmd[-(long)u]) // cmd++ 且 u++;这里是得到cmd[0]
{
case 0x26: pname = (char *)(segname[SEG_ES]);
break;
case 0x2E: pname = (char *)(segname[SEG_CS]);
break;
case 0x36: pname = (char *)(segname[SEG_SS]);
break;
case 0x3E: pname = (char *)(segname[SEG_DS]);
break;
case 0x64: pname = (char *)(segname[SEG_FS]);
break;
case 0x65: pname = (char *)(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;
}
// 该指令罕见,少用
da->cmdtype = C_RARE;
return 1; // Any prefix is 1 byte long
}
// If lock prefix available, display it and forget, because it has no
// influence on对...有影响 decoding of rest of the command.
// 指令存在加锁总线的前缀
if (lockprefix != 0)
{
if (mode >= DISASM_FILE)
nresult += sprintf(da->result + nresult, "LOCK ");
da->warnings |= DAW_LOCK;
}
// Fetch (if available) first 3 bytes of the command, add repeat prefix and
// find command in the command table.
// 取得命令的前三个字节
code = 0;
// 如果指令剩余空间存在
if (size > 0)
*(((char *)&code) + 0) = cmd[0];
if (size > 1)
*(((char *)&code) + 1) = cmd[1];
if (size > 2)
*(((char *)&code) + 2) = cmd[2];
// 如果REP前缀存在
if (repprefix != 0) // RER/REPE/REPNE is considered to be
// 则将其加入到code指令中
code = (code << 8) | repprefix; // part of command.
if (decodevxd && (code & 0xFFFF) == 0x20CD)
pd = &vxdcmd; // Decode VxD call (Win95/98)
else
{
// 遍历指令表
for (pd = cmddata; pd->mask != 0; pd++)
{
// 检测是否pd指令
if (((code ^ pd->code) & pd->mask) != 0)
continue;
// 如果是反汇编模式,并且Use short form of string commands
if (mode >= DISASM_FILE && shortstringcmds &&
// 如果寄存器是ESI或EDI
(pd->arg1 == MSO || pd->arg1 == MDE || pd->arg2 == MSO || pd->arg2 == MDE))
continue; // Search short form of string command
break;
}
}
// Win32 programs usually try to keep stack dword-aligned, so INC ESP
// (44) and DEC ESP (4C) usually don't appear in real code. Also check for
// ADD ESP,imm and SUB ESP,imm (81,C4,imm32; 83,C4,imm8; 81,EC,imm32;
// 83,EC,imm8).
// WIN32程序通常会保持栈的双字对齐, 所以inc esp,dec esp一般不会出现在
// 平常的代码中, 除此同样检测add esp,imm 和 sub esp,imm.
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; // 不常出现的指令
}
// Warn also on MOV SEG,... (8E...). Win32 works in flat mode.
// 警告mov seg,xxx 操作, 因为Win32工作在平坦模式
if (cmd[0] == 0x8E)
da->warnings |= DAW_SEGMENT;
// If opcode is 2-byte, adjust command.
// 如果操作码是2字节的则调整命令
if (pd->len == 2)
{
if (size == 0)
da->error = DAE_CROSS;
else
{
// 工作于反汇编模式
if (mode >= DISASM_FILE)
{
// 将原二进制代码dump至da->dump中
ndump += sprintf(da->dump + ndump, "%02X", *cmd);
// 存储二进制代码
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
srcip++;
size--;
}
}
if (size == 0)
da->error = DAE_CROSS;
// Some commands either feature non-standard data size or have bit which
// allowes to select data size.
// 一些命令的数据长度不是标准的,其长度是可变的
if ((pd->bits & WW) != 0 && (*cmd & WW) == 0)
datasize = 1; // Bit W in command set to 0
else if ((pd->bits & W3) != 0 && (*cmd & W3) == 0)
datasize = 1; // Another position of bit W
else if ((pd->bits & FF) != 0)
datasize = 2; // Forced word (2-byte) size
// Some commands either have mnemonics which depend on data size (8/16 bits
// or 32 bits, like CWD/CDQ), or have several different mnemonics (like
// JNZ/JNE). First case is marked by either '&' (mnemonic depends on
// operand size) or '$' (depends on address size). In the second case,
// there is no special marker and disassembler selects main mnemonic.
// 有些指令的助记符依赖于数据长度(例如CWD/CDQ),或拥有多个不同的助记符
// (例如JNZ/JNE)。第一种情况是使用"&"或"$"标记。第二种情况没有特定标记
// 并被反汇编为主要的助记符
if (mode >= DISASM_FILE)
{
// 指令的助记符依赖于操作数大小
if (pd->name[0] == '&')
mnemosize = datasize;
// 指令的助记符依赖于地址大小
else if (pd->name[0] == '$')
mnemosize = addrsize;
else
mnemosize = 0;
// 助记符大小不为0,依赖数据或地址大小
if (mnemosize != 0)
{
// 遍历pd指令的符号名中每个字符
for (i = 0,j = 1; pd->name[j] != '\0'; j++)
{
// 如果不是":"分割符
if (pd->name[j] == ':')
{
// Separator between 16/32 mnemonics
// 分割符用于分割16位/32位的助记符
if (mnemosize == 4)
i = 0;
else
break;
}
// 指令中如出现"*",则用"W"或"D"代替,作为其长度标记
else if (pd->name[j] == '*')
{
// Substitute替换,代替 by 'W', 'D' or none
if (mnemosize == 4 && sizesens != 2)
name[i++] = 'D';
else if (mnemosize != 4 && sizesens != 0)
name[i++] = 'W';
}
else
name[i++] = pd->name[j];
}
name[i] = '\0';
}
// 否则,说明指令不依赖数据或地址大小
else
{
strcpy(name, pd->name);
// 当指令中有","号分割时,说明该指令有多个
// 助记符,使用主要的一个就行
for (i = 0; name[i] != '\0'; i++)
{
if (name[i] == ',')
{
// Use main mnemonic
name[i] = '\0';
break;
}
}
}
// 将name反汇编后的指令复制至da中
// 存在REP前缀,并且...
if (repprefix != 0 && tabarguments)
{
for (i = 0; name[i] != '\0' && name[i] != ' '; i++)
da->result[nresult++] = name[i];
if (name[i] == ' ')
{
da->result[nresult++] = ' ';
i++;
}
while(nresult < 8)
da->result[nresult++] = ' ';
for ( ; name[i] != '\0'; i++)
da->result[nresult++] = name[i];
}
else
nresult += sprintf(da->result + nresult, "%s", name);
// 要求指令转小写
if (lowercase)
strlwr(da->result);
sprintf_s(da->vm_name, "V%s", name);
}
// Decode operands (explicit - encoded in command, implicit - present in
// mmemonic or assumed - used or modified by command). Assumed operands
// must stay after all explicit and implicit operands. Up to 3 operands
// are allowed.
// 处理操作数,最多可以有3个
for (operand = 0; operand < 3; operand++)
{
stoperand = operand;
// 如果已出错,则直接跳出,不需继续了
if (da->error)
break; // Error - no sense to continue
// If command contains both source and destination, one usually must not
// decode destination to comment because it will be overwritten on the
// next step. Global addcomment takes care of this. Decoding routines,
// however, may ignore this flag.
if (operand == 0 && pd->arg2 != NNN && pd->arg2 < PSEUDOOP)
addcomment = 0;
else
addcomment = 1;
// Get type of next argument.
if (operand == 0)
arg = pd->arg1;
else if (operand == 1)
arg = pd->arg2;
else
arg = pd->arg3;
// 没有更多的操作数了
if (arg == NNN)
break; // No more operands
// Arguments with arg>=PSEUDOOP are assumed operands and are not
// displayed in disassembled result, so they require no delimiter.
// 参数>=PSEUDOOP是假的操作数,并且不显示在反汇编的结果中,所以
// 他们不需要分割符
if ((mode >= DISASM_FILE) && arg < PSEUDOOP) // 添加间隔
{
// 指令与第1个操作数之前有 ' ' 间隔
if (operand == 0)
{
da->result[nresult++] = ' ';
if (tabarguments)
{
while (nresult < 8)
da->result[nresult++] = ' ';
}
}
// 操作数之间则以 ',' 间隔
else
{
da->result[nresult++] = ',';
if (extraspace)
da->result[nresult++] = ' ';
}
}
// Decode, analyse and comment next operand of the command.
// 解码,分析和注释命令的下一个操作数
// 现在正式开始
switch (arg)
{
// 参数是整型寄存器
case REG: // Integer register in Reg field
if (size < 2)
da->error = DAE_CROSS;
else
{
DecodeRG(cmd[1] >> 3, datasize, REG);
}
// 表示指令含有ModRm字节
hasrm = 1;
break;
// 参数是整型寄存器,并嵌入指令中
case RCM: // Integer register in command byte
// 注意:此处下标为0
DecodeRG(cmd[0], datasize, RCM);
break;
// 4字节长度整型寄存器
case RG4: // Integer 4-byte register in Reg field
if (size < 2)
da->error = DAE_CROSS;
else
{
DecodeRG(cmd[1] >> 3, 4, RG4);
}
hasrm = 1;
break;
// 累加器寄存器
case RAC: // Accumulator (AL/AX/EAX, implicit)
DecodeRG(REG_EAX, datasize, RAC);
break;
// AX寄存器
case RAX: // AX (2-byte, implicit)
DecodeRG(REG_EAX, 2, RAX);
break;
// DX寄存器,16位端口地址
case RDX: // DX (16-bit implicit port address)
DecodeRG(REG_EDX, 2, RDX);
break;
// CL寄存器,用于移位
case RCL: // Implicit CL register (for shifts)
DecodeRG(REG_ECX, 1, RCL);
break;
// FPU堆顶寄存器
case RS0: // Top of FPU stack (ST(0))
DecodeST(0, 0);
break;
// FPU寄存器
case RST: // FPU register (ST(i)) in command byte
DecodeST(cmd[0], 0);
break;
// MMX寄存器
case RMX: // MMX register MMx
if (size < 2)
da->error = DAE_CROSS;
else
DecodeMX(cmd[1] >> 3);
hasrm = 1;
break;
// 3DNow寄存器
case R3D: // 3DNow! register MMx
if (size < 2)
da->error = DAE_CROSS;
else
DecodeNR(cmd[1] >> 3);
hasrm = 1;
break;
case MRG: // Memory/register in ModRM byte
case MRJ: // Memory/reg in ModRM as JUMP target
case MR1: // 1-byte memory/register in ModRM byte
case MR2: // 2-byte memory/register in ModRM byte
case MR4: // 4-byte memory/register in ModRM byte
case MR8: // 8-byte memory/MMX register in ModRM
case MRD: // 8-byte memory/3DNow! register in ModRM
case MMA: // Memory address in ModRM byte for LEA
case MML: // Memory in ModRM byte (for LES)
case MM6: // Memory in ModRm (6-byte descriptor)
case MMB: // Two adjacent memory locations (BOUND)
case MD2: // Memory in ModRM byte (16-bit integer)
case MB2: // Memory in ModRM byte (16-bit binary)
case MD4: // Memory in ModRM byte (32-bit integer)
case MD8: // Memory in ModRM byte (64-bit integer)
case MDA: // Memory in ModRM byte (80-bit BCD)
case MF4: // Memory in ModRM byte (32-bit float)
case MF8: // Memory in ModRM byte (64-bit float)
case MFA: // Memory in ModRM byte (80-bit float)
case MFE: // Memory in ModRM byte (FPU environment)
case MFS: // Memory in ModRM byte (FPU state)
case MFX: // Memory in ModRM byte (ext. FPU state)
DecodeMR(arg);
break;
case MMS: // Memory in ModRM byte (as SEG:OFFS)
DecodeMR(arg);
da->warnings |= DAW_FARADDR;
break;
case RR4: // 4-byte memory/register (register only)
case RR8: // 8-byte MMX register only in ModRM
case RRD: // 8-byte memory/3DNow! (register only)
if ((cmd[1] & 0xC0)!=0xC0)
softerror=DAE_REGISTER;
DecodeMR(arg);
break;
case MSO: // Source in string op's ([ESI])
DecodeSO();
break;
case MDE: // Destination in string op's ([EDI])
DecodeDE();
break;
case MXL: // XLAT operand ([EBX+AL])
DecodeXL();
break;
case IMM: // Immediate data (8 or 16/32)
case IMU: // Immediate unsigned data (8 or 16/32)
if ((pd->bits & SS)!=0 && (*cmd & 0x02)!=0)
DecodeIM(1,datasize,arg);
else
DecodeIM(datasize,0,arg);
break;
case VXD: // VxD service (32-bit only)
DecodeVX();//未解决
break;
case IMX: // Immediate sign-extendable byte
DecodeIM(1,datasize,arg);
break;
case C01: // Implicit constant 1 (for shifts)
DecodeC1();//未解决
break;
case IMS: // Immediate byte (for shifts)
case IM1: // Immediate byte
DecodeIM(1,0,arg);
break;
case IM2: // Immediate word (ENTER/RET)
DecodeIM(2,0,arg);
if ((da->immconst & 0x03)!=0)
da->warnings|=DAW_STACK;
break;
case IMA: // Immediate absolute near data address
DecodeIA(); //[imm] ok
break;
case JOB: // Immediate byte offset (for jumps)
DecodeRJ(1,srcip+2);//无须解决jmpconst则是
break;
case JOW: // Immediate full offset (for jumps)
DecodeRJ(datasize,srcip+datasize+1);//无须解决jmpconst则是
break;
case JMF: // Immediate absolute far jump/call addr
DecodeJF();//未解决
da->warnings|=DAW_FARADDR;
break;
case SGM: // Segment register in ModRM byte
if (size<2)
da->error=DAE_CROSS;
DecodeSG(cmd[1]>>3);
hasrm=1;
break;
case SCM: // Segment register in command byte
DecodeSG(cmd[0]>>3);
if ((da->cmdtype & C_TYPEMASK)==C_POP)
da->warnings|=DAW_SEGMENT;
break;
case CRX: // Control register CRx
if ((cmd[1] & 0xC0)!=0xC0)
da->error=DAE_REGISTER;
DecodeCR(cmd[1]);//未解决
break;
case DRX: // Debug register DRx
if ((cmd[1] & 0xC0)!=0xC0)
da->error=DAE_REGISTER;
DecodeDR(cmd[1]);//未解决
break;
case PRN: // Near return address (pseudooperand)
break;
case PRF: // Far return address (pseudooperand)
da->warnings|=DAW_FARADDR;
break;
case PAC: // Accumulator (AL/AX/EAX, pseudooperand)
DecodeRG(REG_EAX,datasize,PAC);
break;
case PAH: // AH (in LAHF/SAHF, pseudooperand)
case PFL: // Lower byte of flags (pseudooperand)
break;
case PS0: // Top of FPU stack (pseudooperand)
DecodeST(0,1);//未解决
break;
case PS1: // ST(1) (pseudooperand)
DecodeST(1,1);//未解决
break;
case PCX: // CX/ECX (pseudooperand)
DecodeRG(REG_ECX,cxsize,PCX);
break;
case PDI: // EDI (pseudooperand in MMX extentions)
DecodeRG(REG_EDI,4,PDI);
break;
default:
da->error=DAE_INTERN; // Unknown argument type
break;
}
da->memsize[operand] = datasize;
}
// Check whether command may possibly contain fixups.
if (pfixup != NULL && da->fixupsize > 0)
da->fixupoffset = (int)(pfixup - src);
// Segment prefix and address size prefix are superfluous for command which
// does not access memory. If this the case, mark command as rare to help
// in analysis.
// 段前缀与地址大小前缀过多
if (da->memtype == DEC_UNKNOWN &&
(segprefix != SEG_UNDEF || (addrsize != 4 && pd->name[0] != '$')))
{
da->warnings |= DAW_PREFIX;
da->cmdtype |= C_RARE;
}
// 16-bit addressing is rare in 32-bit programs. If this is the case,
// mark command as rare to help in analysis.
// 16位的寻址在32位程序中是少见的,如果是这种情况,在命令中加上标志
if (addrsize != 4)
da->cmdtype |= C_RARE;
}
// Suffix of 3DNow! command is accounted best by assuming it immediate byte
// constant.
// 如果是一个3dNow指令
if (is3dnow)
{
if (immsize != 0)
da->error = DAE_BADCMD;
else
immsize = 1;
}
// Right or wrong, command decoded. Now dump it.
if (da->error != 0) // 如果命令有错误
{
// Hard error in command detected
if (mode >= DISASM_FILE)
nresult = sprintf(da->result, "???");
if (da->error == DAE_BADCMD && (*cmd == 0x0F || *cmd == 0xFF) && size > 0)
{
if (mode >= DISASM_FILE)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd);
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
size--;
}
if (size>0)
{
if (mode >= DISASM_FILE)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd);
da->hexcode[da->codelen++] = *cmd;
}
cmd++;
size--;
}
}
else
{
//如果没有错误,dump命令
// No hard error, dump command
if (mode >= DISASM_FILE)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd++);
da->hexcode[da->codelen++] = *(cmd - 1);
if (hasrm)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd++);
da->hexcode[da->codelen++] = *(cmd - 1);
}
if (hassib)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd++);
da->hexcode[da->codelen++] = *(cmd - 1);
}
if (dispsize != 0)
{
da->dump[ndump++] = ' ';
for (i = 0; i < dispsize; i++)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd++);
da->hexcode[da->codelen++] = *(cmd - 1);
}
}
if (immsize != 0)
{
da->dump[ndump++] = ' ';
for (i = 0; i < immsize; i++)
{
ndump += sprintf(da->dump + ndump, "%02X", *cmd++);
da->hexcode[da->codelen++] = *(cmd - 1);
}
}
}
else
cmd += 1 + hasrm + hassib + dispsize + immsize;
size -= 1 + hasrm + hassib + dispsize + immsize;
}
// Check that command is not a dangerous one.
// 检查命令是否是危险的
if (mode >= DISASM_DATA)
{
for (pdan = dangerous; pdan->mask != 0; pdan++)
{
if (((code ^ pdan->code) & pdan->mask) != 0)
continue;
if (pdan->type == C_DANGERLOCK && lockprefix == 0)
break; // Command harmless without LOCK prefix
if (iswindowsnt && pdan->type == C_DANGER95)
break; // Command harmless under Windows NT
// Dangerous command!
if (pdan->type == C_DANGER95)
da->warnings |= DAW_DANGER95;
else
da->warnings |= DAW_DANGEROUS;
break;
}
}
if (da->error == 0 && softerror != 0)
da->error = softerror; // Error, but still display command
if (mode >= DISASM_FILE)
{
// 根据错误处理
if (da->error != DAE_NOERR)
{
switch (da->error)
{
case DAE_CROSS:
strcpy(da->comment, "Command crosses end of memory block");
break;
case DAE_BADCMD:
strcpy(da->comment, "Unknown command");
break;
case DAE_BADSEG:
strcpy(da->comment, "Undefined segment register");
break;
case DAE_MEMORY:
strcpy(da->comment, "Illegal use of register");
break;
case DAE_REGISTER:
strcpy(da->comment, "Memory address not allowed");
break;
case DAE_INTERN:
strcpy(da->comment, "Internal OLLYDBG error");
break;
default:
strcpy(da->comment, "Unknown error");
break;
}
}
// 特权指令,发出警告
else if ((da->warnings & DAW_PRIV) != 0 && privileged == 0)
strcpy(da->comment, "Privileged command");
// IO指令
else if ((da->warnings & DAW_IO) != 0 && iocommand == 0)
strcpy(da->comment, "I/O command");
else if ((da->warnings & DAW_FARADDR) != 0 && farcalls == 0)
{
if ((da->cmdtype & C_TYPEMASK) == C_JMP)
strcpy(da->comment, "Far jump");
else if ((da->cmdtype & C_TYPEMASK) == C_CAL)
strcpy(da->comment, "Far call");
else if ((da->cmdtype & C_TYPEMASK) == C_RET)
strcpy(da->comment, "Far return");
}
else if ((da->warnings & DAW_SEGMENT) != 0 && farcalls == 0)
strcpy(da->comment, "Modification of segment register");
else if ((da->warnings & DAW_SHIFT) != 0 && badshift == 0)
strcpy(da->comment, "Shift constant out of range 1..31");
else if ((da->warnings & DAW_PREFIX) != 0 && extraprefix == 0)
strcpy(da->comment, "Superfluous prefix");
else if ((da->warnings & DAW_LOCK) != 0 && lockedbus == 0)
strcpy(da->comment, "LOCK prefix");
else if ((da->warnings & DAW_STACK) != 0 && stackalign == 0)
strcpy(da->comment, "Unaligned stack operation");
}
return (srcsize - size); // Returns number of recognized bytes
}
// --------------------------- disasm.h -------------
// Free Disassembler and Assembler -- Header file
//
// 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
#pragma once
// If you prefere Borland, this will force necessary setting (but, as a side
// effect, may cause plenty of warnings if other include files will be compiled
// with different options):
#ifdef __BORLANDC__
#pragma option -K // Unsigned char
#endif
//
//#if (char)0xFF != 255
//#error Please set default char type to unsigned
//#endif
#define NEGLIMIT (-16384) // Limit to display constans as signed
// 假操作数,伪操作数
#define PSEUDOOP 128 // Base for pseudooperands
#define TEXTLEN 256 // Maximal length of text string
// Special command features.
#define WW 0x01 // Bit W (size of operand)
#define SS 0x02 // Bit S (sign extention of immediate)
#define WS 0x03 // Bits W and S
#define W3 0x08 // Bit W at position 3
#define CC 0x10 // Conditional jump
// 强制要求16位长度的操作数
#define FF 0x20 // Forced 16-bit size
#define LL 0x40 // Conditional loop
// 特权指令
#define PR 0x80 // Protected command
// IO指令
#define WP 0x81 // I/O command with bit W
// All possible types of operands in 80x86. A bit more than you expected, he?
// 操作数类型
#define NNN 0 // No operand \\ 无操作
// 当操作数必须是内存操作数,而发现操作数是寄存器时出的错误
#define DAE_MEMORY 4 // Register where only memory allowed
#define DAE_REGISTER 5 // Memory where only register allowed
// 内部错误
#define DAE_INTERN 6 // Internal error
typedef unsigned char uchar; // Unsigned character (byte)
typedef unsigned short ushort; // Unsigned short
typedef unsigned int uint; // Unsigned integer
typedef unsigned long ulong; // Unsigned long
typedef struct t_addrdec
{
int defseg;
char *descr;
} t_addrdec;
// 命令数据
typedef struct t_cmddata
{
ulong mask; // Mask for first 4 bytes of the command
ulong code; // Compare masked bytes with this
char len; // Length of the main command code
// 例如PR,则表明该指令是一特权指令(ring 0指令)
// FF:强制操作数为16位操作数
char bits; // Special bits within the command
char arg1,arg2,arg3; // Types of possible arguments
char type; // C_xxx + additional information
char *name; // Symbolic name for this command
} t_cmddata;
// Initialized constant data structures used by all programs from assembler
// package. Contain names of register, register combinations or commands and
// their properties.
extern const char *regname[3][9];
extern const char *segname[8];
extern const char *sizename[11];
extern const t_addrdec addr16[8];
extern const t_addrdec addr32[8];
extern const char *fpuname[9];
extern const char *mmxname[9];
extern const char *crname[9];
extern const char *drname[9];
extern const char *condition[16];
extern const t_cmddata cmddata[];//可用结构数组
extern const t_cmddata vxdcmd;
extern const t_cmddata dangerous[];
////////////////////////////////////////////////////////////////////////////////
//////////////////// ASSEMBLER, DISASSEMBLER AND EXPRESSIONS ///////////////////
#define MAXCMDSIZE 16 // Maximal length of 80x86 command
#define MAXCALSIZE 8 // Max length of CALL without prefixes
#define NMODELS 8 // Number of assembler search models
#define INT3 0xCC // Code of 1-byte breakpoint
#define NOP 0x90 // Code of 1-byte NOP command
#define TRAPFLAG 0x00000100 // Trap flag in CPU flag register
// 指令有加锁总线前缀
#define DAW_LOCK 0x0040 // Command has LOCK prefix
// 栈没有对齐(一般栈操作需要双字对齐)
#define DAW_STACK 0x0080 // Unaligned stack operation
#define DAW_DANGER95 0x1000 // May mess up Win95 if executed
#define DAW_DANGEROUS 0x3000 // May mess up any OS if executed
// 1:表示adrconst为0
int zeroconst; // Whether contains zero constant
int fixupoffset; // Possible offset of 32-bit fixups
int fixupsize; // Possible total size of fixups or 0
int error; // Error while disassembling command
// 反汇编过程中需要进行警告的信息
// 如DAW_PRIV,则表明指令是一个特权指令(ring 0)指令
int warnings; // Combination of DAW_xxx
//bughoho new
BYTE hexcode[TEXTLEN]; // 用于存储2进制码
int codelen; // 长度
int optype[3]; // 操作数类型
char vm_name[TEXTLEN]; // 声称VM对应的Handler名称
// 3dNow指令
int is3dnow; // 3dnow函数
int segment; // 保存段前缀
// 当操作数为寄存器时,存储寄存器编号
int reg[3]; // 3寄存器(假设操作数为寄存器)
int segreg; // 段寄存器(假设操作数为段寄存器)
int addrreg1; // 内存地址部分的第1个不带比例的寄存器
int addrreg2; // 内存地址部分的第2个带比例的寄存器
int regsscale; // 比例:1,2,4,8
//还有一个adrconst已经定义,根据正负号来定义加减
int memsize[3]; // 操作数长度
/**
* 虚拟机指令相应的汇编代码必须编译成二进制机器代码,此结构就用于
* 表示某段编译之后的二进制机器代码及代码的一些相关信息
*/
typedef struct t_asmmodel
{ // Model to search for assembler command
// 存储解码后的机器指令
char code[MAXCMDSIZE]; // Binary code
char mask[MAXCMDSIZE]; // Mask for binary code (0: bit ignored)
// 指令长度
int length; // Length of code, bytes (0: empty)
int jmpsize; // Offset size if relative jump
int jmpoffset; // Offset relative to IP
int jmppos; // Position of jump offset in command
} t_asmmodel;
odunique int ideal; // Force IDEAL decoding mode
odunique int lowercase; // Force lowercase display
odunique int tabarguments; // Tab between mnemonic and arguments
odunique int extraspace; // Extra space between arguments
odunique int putdefseg; // Display default segments in listing
odunique int showmemsize; // Always show memory size
odunique int shownear; // Show NEAR modifiers
odunique int shortstringcmds; // Use short form of string commands
odunique int sizesens; // How to decode size-sensitive mnemonics
odunique int symbolic; // Show symbolic addresses in disasm
odunique int farcalls; // Accept far calls, returns & addresses
odunique int decodevxd; // Decode VxD calls (Win95/98)
odunique int privileged; // Accept privileged commands
odunique int iocommand; // Accept I/O commands
odunique int badshift; // Accept shift out of range 1..31
odunique int extraprefix; // Accept superfluous prefixes
odunique int lockedbus; // Accept LOCK prefixes
odunique int stackalign; // Accept unaligned stack operations
odunique int iswindowsnt; // When checking for dangers, assume NT
//bughoho
odunique int stoperand; //当前的循环
int Assemble(char *cmd,ulong ip,t_asmmodel *model,int attempt,
int constsize,char *errtext);
int Checkcondition(int code,ulong flags);
int Decodeaddress(ulong addr,char *symb,int nsymb,char *comment);
ulong Disasm(char *src,ulong srcsize,ulong srcip,
t_disasm *disasm,int disasmmode);
ulong Disassembleback(char *block,ulong base,ulong size,ulong ip,int n);
ulong Disassembleforward(char *block,ulong base,ulong size,ulong ip,int n);
int Isfilling(ulong addr,char *data,ulong size,ulong align);
int Print3dnow(char *s,char *f);
int Printfloat10(char *s,long double ext);
int Printfloat4(char *s,float f);
int Printfloat8(char *s,double d);