📄 assembl.c
字号:
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*=decimal*base;
// floating*=pow10l(decimal*base);
};
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) {
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";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -