📄 assembl.cpp
字号:
{
if (sign=='-')
{
asmerror="Unable to subtract register"; scan=SCAN_ERR;
return;
};
if (xlataddr!=0)
{
asmerror="Too many registers";
scan=SCAN_ERR;
return;
};
xlataddr=1;
Scanasm(0);
}
else if (scan==SCAN_REG16)
{
asmerror="Sorry, 16-bit addressing is not supported";
scan=SCAN_ERR;
return;
}
else if (scan==SCAN_REG32)
{
if (sign=='-')
{
asmerror="Unable to subtract register";
scan=SCAN_ERR; return;
};
reg=idata; Scanasm(0);
if (scan==SCAN_SYMB && idata=='*')
{
Scanasm(0); // Try index*scale
if (scan==SCAN_ERR)
return;
if (scan==SCAN_OFS)
{
asmerror="Undefined scale is not allowed";
scan=SCAN_ERR;
return;
};
if (scan!=SCAN_ICONST && scan!=SCAN_DCONST)
{
asmerror="Syntax error";
scan=SCAN_ERR;
return;
};
if (idata==6 || idata==7 || idata>9)
{
asmerror="Invalid scale";
scan=SCAN_ERR;
return;
};
r[reg]+=idata;
Scanasm(0);
}
else
r[reg]++;
} // Simple register
else if (scan==SCAN_LOCAL)
{
r[REG_EBP]++;
op->offset-=idata*4;
Scanasm(0);
}
else if (scan==SCAN_ARG)
{
r[REG_EBP]++;
op->offset+=(idata+1)*4;
Scanasm(0);
}
else if (scan==SCAN_ICONST || scan==SCAN_DCONST)
{
offset=idata;
Scanasm(0);
if (scan==SCAN_SYMB && idata=='*')
{
Scanasm(0); // Try scale*index
if (scan==SCAN_ERR)
return;
if (sign=='-')
{
asmerror="Unable to subtract register";
scan=SCAN_ERR;
return;
};
if (scan==SCAN_REG16)
{
asmerror="Sorry, 16-bit addressing is not supported";
scan=SCAN_ERR;
return;
};
if (scan!=SCAN_REG32)
{
asmerror="Syntax error";
scan=SCAN_ERR;
return;
};
if (offset==6 || offset==7 || offset>9)
{
asmerror="Invalid scale";
scan=SCAN_ERR;
return;
};
r[idata]+=offset;
Scanasm(0);
}
else
{
if (sign=='-')
op->offset-=offset;
else
op->offset+=offset;
};
}
else if (scan==SCAN_OFS)
{
Scanasm(0);
if (scan==SCAN_SYMB && idata=='*')
{
asmerror="Undefined scale is not allowed"; scan=SCAN_ERR; return; }
else
{
op->anyoffset=1;
};
}
else
break; // None of expected address elements
if (scan==SCAN_SYMB && idata==']')
break;
sign='?';
};
if (scan==SCAN_ERR)
return;
if (scan!=SCAN_SYMB || idata!=']')
{
asmerror="Syntax error";
scan=SCAN_ERR;
return;
};
// Process XLAT address separately.
if (xlataddr!=0)
{ // XLAT address in form [EBX+AX]
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;
};
op->type=MXL;
}
// Determine scale, index and base.
else
{
j=0; // Number of used registers
for (i=0; i<=8; i++)
{
if (r[i]==0)
continue; // Unused register
if (r[i]==3 || r[i]==5 || r[i]==9)
{
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;
op->scale=r[i]-1;
}
else if (r[i]==2 || r[i]==4 || r[i]==8)
{
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];
}
else if (r[i]==1)
{
if (op->base<0)
op->base=i;
else if (op->index<0)
{
op->index=i;
op->scale=1;
}
else
{
asmerror="Too many registers";
scan=SCAN_ERR;
return;
};
}
else
{
asmerror="Invalid scale";
scan=SCAN_ERR;
return;
};
j++;
};
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().
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 incomplete 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
int Assemble(char *cmd,ulong ip,t_asmmodel *model,int attempt,int constsize,char *errtext)
{
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;
char name[32],*nameend;
char tcode[MAXCMDSIZE],tmask[MAXCMDSIZE];
t_asmoperand aop[3],*op; // Up to 3 operands allowed
const t_cmddata *pd;
if (model!=NULL)
model->length=0;
if (cmd==NULL || model==NULL || errtext==NULL)
{
if (errtext!=NULL)
strcpy(errtext,"Internal OLLYDBG error");
return 0;
}; // Error in parameters
asmcmd=cmd;
rep=lock=0; errtext[0]='\0';
Scanasm(SA_NAME);
if (scan==SCAN_EOL) // End of line, nothing to assemble
return 0;
while (1)
{ // Fetch all REPxx and LOCK prefixes
if (scan==SCAN_REP || scan==SCAN_REPE || scan==SCAN_REPNE)
{
if (rep!=0)
{
strcpy(errtext,"Duplicated REP prefix");
goto error;
};
rep=scan;
}
else if (scan==SCAN_LOCK)
{
if (lock!=0)
{
strcpy(errtext,"Duplicated LOCK prefix");
goto error;
};
lock=scan;
}
else
break; // No more prefixes
Scanasm(SA_NAME);
};
if (scan!=SCAN_NAME || idata>16)
{
strcpy(errtext,"Command mnemonic expected");
goto error;
};
nameend=asmcmd;
strupr(sdata);
// 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);
Scanasm(0);
// Parse command operands (up to 3). Note: jump address is always the first
// (and only) operand in actual command set.
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
Parseasmoperand(aop+0);
jmpmode=aop[0].jmpmode;
if (jmpmode!=0) jmpmode|=0x80;
if (scan==SCAN_SYMB && idata==',')
{
Scanasm(0);
Parseasmoperand(aop+1);
if (scan==SCAN_SYMB && idata==',')
{
Scanasm(0);
Parseasmoperand(aop+2);
};
};
if (scan==SCAN_ERR)
{
strcpy(errtext,asmerror); goto error;
};
if (scan!=SCAN_EOL)
{
strcpy(errtext,"Extra input after operand");
goto error;
};
// If jump size is not specified, function tries to use short jump. If
// attempt fails, it retries with long form.
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.
namelen=(int)strlen(name);
for (pd=cmddata; pd->mask!=0; pd++)
{
if (pd->name[0]=='&')
{ // Mnemonic depends on operand size
j=1;
datasize=2;
addrsize=4;
while (1)
{ // Try all mnemonics (separated by ':')
for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++)
{
if (pd->name[j]=='*')
{
if (name[i]=='W')
{
datasize=2;
i++;
}
else if (name[i]=='D')
{
datasize=4;
i++;
}
else if (sizesens==0)
datasize=2;
else
datasize=4;
}
else if (pd->name[j]==name[i])
i++;
else
break;
};
if (name[i]=='\0' && (pd->name[j]=='\0' || pd->name[j]==':'))
break; // Bingo!
while (pd->name[j]!='\0' && pd->name[j]!=':')
j++;
if (pd->name[j]==':')
{
j++; datasize=4;
} // Retry with 32-bit mnenonic
else
{
i=0;
break; // Comparison failed
};
};
if (i==0)
continue;
}
else if (pd->name[0]=='$') // Mnemonic depends on address size
{
j=1;
datasize=0;
addrsize=2;
while (1)
{ // Try all mnemonics (separated by ':')
for (i=0; pd->name[j]!='\0' && pd->name[j]!=':'; j++)
{
if (pd->name[j]=='*')
{
if (name[i]=='W')
{
addrsize=2;
i++;
}
else if (name[i]=='D')
{ addrsize=4; i++;
}
else if (sizesens==0)
addrsize=2;
else
addrsize=4;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -