?? assembl.c
字號:
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;
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=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; }
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++; addrsize=4; } // Retry with 32-bit mnenonic
else {
i=0; break; // Comparison failed
};
};
if (i==0) continue; }
else { // Compare with all synonimes
j=k=0;
datasize=0; // Default settings
addrsize=4;
while (1) {
while (pd->name[j]!=',' && pd->name[j]!='\0') j++;
if (j-k==namelen && strnicmp(name,pd->name+k,namelen)==0) break;
k=j+1; if (pd->name[j]=='\0') break;
j=k; };
if (k>j) continue;
};
// For error diagnostics it is important to know whether mnemonic exists.
nameok++;
if (pd->arg1==NNN || pd->arg1>=PSEUDOOP)
minop=0;
else if (pd->arg2==NNN || pd->arg2>=PSEUDOOP) {
if (minop>1) minop=1;
if (maxop<1) maxop=1; }
else if (pd->arg3==NNN || pd->arg3>=PSEUDOOP) {
if (minop>2) minop=2;
if (maxop<2) maxop=2; }
else
maxop=3;
// Determine default and allowed operand size(s).
if (pd->bits==FF) datasize=2; // Forced 16-bit size
if (pd->bits==WW || pd->bits==WS || pd->bits==W3 || pd->bits==WP)
bytesize=1; // 1-byte size allowed
else
bytesize=0; // Word/dword size only
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -