📄 assembl.cpp
字号:
};
asmcmd++;
idata=hex; scan=SCAN_ICONST;
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++;
return;
};
if (*asmcmd=='.')
{ // Force decimal number
if (base==16 || maxdigit>9)
{
asmerror="Not a decimal number";
scan=SCAN_ERR;
return;
};
asmcmd++;
if (isdigit(*asmcmd) || toupper(*asmcmd)=='E')
{
divisor=1.0;
while (isdigit(*asmcmd))
{ // Floating-point number
divisor/=10.0;
floating+=divisor*(*asmcmd-'0');
asmcmd++;
};
if (toupper(*asmcmd)=='E')
{
asmcmd++;
if (*asmcmd=='-')
{
base=-1;
asmcmd++;
}
else
base=1;
if (!isdigit(*asmcmd))
{
asmerror="Invalid exponent";
scan=SCAN_ERR;
return;
};
decimal=0;
while (isdigit(*asmcmd))
{
if (decimal<65536L)
decimal=decimal*10+(*asmcmd++)-'0';
};
floating*=powl(decimal*base,1);
};
fdata=floating;
scan=SCAN_FCONST;
return;
}
else
{
idata=decimal;
scan=SCAN_DCONST;
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++;
return;
};
};
idata=hex;
scan=SCAN_ICONST; // Default is hexadecimal
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++;
return;
}
else if (*asmcmd=='\'')
{ // Character constant
asmcmd++;
if (*asmcmd=='\0' || (*asmcmd=='\\' && asmcmd[1]=='\0'))
{
asmerror="Unterminated character constant";
scan=SCAN_ERR;
return;
};
if (*asmcmd=='\'')
{
asmerror="Empty character constant";
scan=SCAN_ERR;
return;
};
if (*asmcmd=='\\')
asmcmd++;
idata=*asmcmd++;
if (*asmcmd!='\'')
{
asmerror="Unterminated character constant";
scan=SCAN_ERR;
return;
};
asmcmd++;
while (*asmcmd==' ' || *asmcmd=='\t')
asmcmd++;
scan=SCAN_ICONST;
return;
}
else
{ // Any other character or combination
idata=sdata[0]=*asmcmd++; sdata[1]=sdata[2]='\0';
if (idata=='|' && *asmcmd=='|')
{
idata='||'; prio=10; // '||'
sdata[1]=*asmcmd++;
}
else if (idata=='&' && *asmcmd=='&')
{
idata='&&'; prio=9; // '&&'
sdata[1]=*asmcmd++;
}
else if (idata=='=' && *asmcmd=='=')
{
idata='=='; prio=5; // '=='
sdata[1]=*asmcmd++;
}
else if (idata=='!' && *asmcmd=='=')
{
idata='!='; prio=5; // '!='
sdata[1]=*asmcmd++;
}
else if (idata=='<' && *asmcmd=='=')
{
idata='<='; prio=4; // '<='
sdata[1]=*asmcmd++;
}
else if (idata=='>' && *asmcmd=='=')
{
idata='>='; prio=4; // '>='
sdata[1]=*asmcmd++;
}
else if (idata=='<' && *asmcmd=='<')
{
idata='<<'; prio=3; // '<<'
sdata[1]=*asmcmd++;
}
else if (idata=='>' && *asmcmd=='>')
{
idata='>>'; prio=3; // '>>'
sdata[1]=*asmcmd++;
}
else if (idata=='|')
prio=8; // '|'
else if (idata=='^')
prio=7; // '^'
else if (idata=='&')
prio=6; // '&'
else if (idata=='<')
{
if (*asmcmd=='&')
{ // Import pseudolabel (for internal use)
if ((mode & SA_IMPORT)==0)
{
asmerror="Syntax error";
scan=SCAN_ERR; return;
};
asmcmd++; i=0;
while (*asmcmd!='\0' && *asmcmd!='>')
{
sdata[i++]=*asmcmd++;
if (i>=sizeof(sdata))
{
asmerror="Too long import name";
scan=SCAN_ERR;
return;
};
};
if (*asmcmd!='>')
{
asmerror="Unterminated import name";
scan=SCAN_ERR;
return;
};
asmcmd++;
sdata[i]='\0';
scan=SCAN_IMPORT;
return;
}
else prio=4;
} // '<'
else if (idata=='>')
prio=4; // '>'
else if (idata=='+')
prio=2; // '+'
else if (idata=='-')
prio=2; // '-'
else if (idata=='*')
prio=1; // '*'
else if (idata=='/')
prio=1; // '/'
else if (idata=='%')
prio=1; // '%'
else if (idata==']')
{
pcmd=asmcmd;
Scanasm(SA_NAME);
if (scan!=SCAN_SYMB || idata!='[')
{
idata=']';
asmcmd=pcmd;
prio=0;
}
else
{
idata='+'; prio=2; // Translate '][' to '+'
};
}
else
prio=0; // Any other character
scan=SCAN_SYMB;
return;
};
};
// 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).
static void Parseasmoperand(t_asmoperand *op)
{
int i,j,bracket,sign,xlataddr;
int reg,r[9];
long offset;
if (scan==SCAN_EOL || scan==SCAN_ERR)
return; // No or bad operand
// 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().
if (scan==SCAN_JMPSIZE)
{
j=0;
while (scan==SCAN_JMPSIZE)
{
j|=idata; // Fetch all size modifiers
Scanasm(0);
};
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;
};
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.
if (scan==SCAN_REG8 || scan==SCAN_REG16 || scan==SCAN_REG32)
{
op->type=REG;
op->index=idata; // Integer general-purpose register
if (scan==SCAN_REG8)
op->size=1;
else if (scan==SCAN_REG16)
op->size=2;
else
op->size=4;
}
else if (scan==SCAN_FPU)
{ // FPU register
op->type=RST;
op->index=idata;
}
else if (scan==SCAN_MMX)
{ // MMX or 3DNow! register
op->type=RMX;
op->index=idata;
}
else if (scan==SCAN_CR)
{ // Control register
op->type=CRX;
op->index=idata;
}
else if (scan==SCAN_DR)
{ // Debug register
op->type=DRX;
op->index=idata;
}
else if (scan==SCAN_SYMB && idata=='-')
{
Scanasm(0); // Negative constant
if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS)
{
asmerror="Integer number expected";
scan=SCAN_ERR;
return;
};
op->type=IMM;
op->offset=-idata;
if (scan==SCAN_OFS)
op->anyoffset=1;
}
else if (scan==SCAN_SYMB && idata=='+')
{
Scanasm(0); // Positive constant
if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS)
{
asmerror="Integer number expected";
scan=SCAN_ERR;
return;
};
op->type=IMM;
op->offset=idata;
if (scan==SCAN_OFS)
op->anyoffset=1;
}
else if (scan==SCAN_ICONST || scan==SCAN_DCONST || scan==SCAN_OFS)
{
j=idata;
if (scan==SCAN_OFS)
op->anyoffset=1;
Scanasm(0);
if (scan==SCAN_SYMB && idata==':')
{
Scanasm(0); // Absolute long address (seg:offset)
if (scan!=SCAN_ICONST && scan!=SCAN_DCONST && scan!=SCAN_OFS)
{
asmerror="Integer address expected";
scan=SCAN_ERR;
return;
};
op->type=JMF;
op->offset=idata;
op->segment=j;
if (scan==SCAN_OFS)
op->anyoffset=1;
}
else
{
op->type=IMM;
op->offset=j; // Constant without sign
return; // Next token already scanned
};
}
else if (scan==SCAN_FCONST)
{
asmerror="Floating-point numbers are not allowed in command";
scan=SCAN_ERR;
return;
}
// Segment register or address.
else if (scan==SCAN_SEG || scan==SCAN_OPSIZE || (scan==SCAN_SYMB && idata=='[') )
{ // Segment register or address
bracket=0;
if (scan==SCAN_SEG)
{
j=idata; Scanasm(0);
if (scan!=SCAN_SYMB || idata!=':')
{
op->type=SGM; op->index=j; // Segment register as operand
return;
}; // Next token already scanned
op->segment=j;
Scanasm(0);
};
// 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;
}
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 nigthmare, 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].
for (i=0; i<=8; i++) r[i]=0;
sign='+'; // Default sign for the first operand
xlataddr=0;
while (1)
{ // Get SIB and offset
if (scan==SCAN_SYMB && (idata=='+' || idata=='-'))
{
sign=idata; Scanasm(0);
};
if (scan==SCAN_ERR)
return;
if (sign=='?')
{
asmerror="Syntax error";
scan=SCAN_ERR;
return; };
// Register AL appears as part of operand of (seldom used) command XLAT.
if (scan==SCAN_REG8 && idata==REG_EAX)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -