?? assembl.c
字號:
// Check whether command operands match specified. If so, variable match
// remains zero, otherwise it contains kind of mismatch. This allows for
// better error diagnostics.
match=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 || arg>=PSEUDOOP) {
if (op->type!=NNN) // No more arguments
match|=MA_NOP;
break; };
if (op->type==NNN) {
match|=MA_NOP; break; }; // No corresponding operand
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;
if (arg==RAC && op->index!=REG_EAX && op->index!=8) match|=MA_TYP;
if (bytesize==0 && op->size==1) match|=MA_SIZ;
if (datasize==0) datasize=op->size;
if (datasize!=op->size) match|=MA_DIF;
break;
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;
case RAX: // AX (2-byte, implicit)
if (op->type!=REG || (op->index!=REG_EAX && op->index!=8))
match|=MA_TYP;
if (op->size!=2) match|=MA_SIZ;
if (datasize==0) datasize=op->size;
if (datasize!=op->size) match|=MA_DIF;
break;
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;
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;
case RS0: // Top of FPU stack (ST(0))
if (op->type!=RST || (op->index!=0 && op->index!=8))
match|=MA_TYP;
break;
case RST: // FPU register (ST(i)) in command byte
if (op->type!=RST) match|=MA_TYP; break;
case RMX: // MMX register MMx
case R3D: // 3DNow! register MMx
if (op->type!=RMX) match|=MA_TYP; break;
case MRG: // Memory/register in ModRM byte
if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
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;
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;
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;
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;
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;
case MRJ: // Memory/reg in ModRM as JUMP target
if (op->type!=MRG && op->type!=REG) match|=MA_TYP;
if (op->size!=0 && op->size!=4) match|=MA_SIZ;
if ((jmpmode & 0x09)!=0) match|=MA_JMP;
jmpmode&=0x7F; break;
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;
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) match|=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;
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)
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
// 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;
};
// Exact match found. Now construct the code.
hasrm=0; // Whether command has ModR/M byte
hassib=0; // Whether command has SIB byte
dispsize=0; // Size of displacement (if any)
immsize=0; // Size of immediate data (if any)
segment=SEG_UNDEF; // Necessary segment prefix
jmpsize=0; // No relative jumps
memset(tcode,0,sizeof(tcode));
*(ulong *)tcode=pd->code & pd->mask;
memset(tmask,0,sizeof(tmask));
*(ulong *)tmask=pd->mask;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -