📄 parser.c
字号:
i = stdscan(NULL, &tokval); /* eat the comma */
continue;
}
}
/* anything else */
{
expr *value;
value = evaluate(stdscan, NULL, &tokval, NULL,
critical, error, NULL);
i = tokval.t_type;
if (!value) { /* error in evaluator */
result->opcode = -1; /* unrecoverable parse error: */
return result; /* ignore this instruction */
}
if (is_unknown(value)) {
eop->type = EOT_DB_NUMBER;
eop->offset = 0; /* doesn't matter what we put */
eop->segment = eop->wrt = NO_SEG; /* likewise */
} else if (is_reloc(value)) {
eop->type = EOT_DB_NUMBER;
eop->offset = reloc_value(value);
eop->segment = reloc_seg(value);
eop->wrt = reloc_wrt(value);
} else {
error(ERR_NONFATAL,
"operand %d: expression is not simple"
" or relocatable", oper_num);
}
}
/*
* We're about to call stdscan(), which will eat the
* comma that we're currently sitting on between
* arguments. However, we'd better check first that it
* _is_ a comma.
*/
if (i == 0) /* also could be EOL */
break;
if (i != ',') {
error(ERR_NONFATAL, "comma expected after operand %d",
oper_num);
result->opcode = -1; /* unrecoverable parse error: */
return result; /* ignore this instruction */
}
}
if (result->opcode == I_INCBIN) {
/*
* Correct syntax for INCBIN is that there should be
* one string operand, followed by one or two numeric
* operands.
*/
if (!result->eops || result->eops->type != EOT_DB_STRING)
error(ERR_NONFATAL, "`incbin' expects a file name");
else if (result->eops->next &&
result->eops->next->type != EOT_DB_NUMBER)
error(ERR_NONFATAL, "`incbin': second parameter is",
" non-numeric");
else if (result->eops->next && result->eops->next->next &&
result->eops->next->next->type != EOT_DB_NUMBER)
error(ERR_NONFATAL, "`incbin': third parameter is",
" non-numeric");
else if (result->eops->next && result->eops->next->next &&
result->eops->next->next->next)
error(ERR_NONFATAL,
"`incbin': more than three parameters");
else
return result;
/*
* If we reach here, one of the above errors happened.
* Throw the instruction away.
*/
result->opcode = -1;
return result;
} else /* DB ... */ if (oper_num == 0)
error(ERR_WARNING | ERR_PASS1,
"no operand for data declaration");
else
result->operands = oper_num;
return result;
}
/* right. Now we begin to parse the operands. There may be up to three
* of these, separated by commas, and terminated by a zero token. */
for (operand = 0; operand < 3; operand++) {
expr *value; /* used most of the time */
int mref; /* is this going to be a memory ref? */
int bracket; /* is it a [] mref, or a & mref? */
int setsize = 0;
result->oprs[operand].addr_size = 0; /* have to zero this whatever */
result->oprs[operand].eaflags = 0; /* and this */
result->oprs[operand].opflags = 0;
i = stdscan(NULL, &tokval);
if (i == 0)
break; /* end of operands: get out of here */
result->oprs[operand].type = 0; /* so far, no override */
while (i == TOKEN_SPECIAL) { /* size specifiers */
switch ((int)tokval.t_integer) {
case S_BYTE:
if (!setsize) /* we want to use only the first */
result->oprs[operand].type |= BITS8;
setsize = 1;
break;
case S_WORD:
if (!setsize)
result->oprs[operand].type |= BITS16;
setsize = 1;
break;
case S_DWORD:
case S_LONG:
if (!setsize)
result->oprs[operand].type |= BITS32;
setsize = 1;
break;
case S_QWORD:
if (!setsize)
result->oprs[operand].type |= BITS64;
setsize = 1;
break;
case S_TWORD:
if (!setsize)
result->oprs[operand].type |= BITS80;
setsize = 1;
break;
case S_TO:
result->oprs[operand].type |= TO;
break;
case S_STRICT:
result->oprs[operand].type |= STRICT;
break;
case S_FAR:
result->oprs[operand].type |= FAR;
break;
case S_NEAR:
result->oprs[operand].type |= NEAR;
break;
case S_SHORT:
result->oprs[operand].type |= SHORT;
break;
default:
error(ERR_NONFATAL, "invalid operand size specification");
}
i = stdscan(NULL, &tokval);
}
if (i == '[' || i == '&') { /* memory reference */
mref = TRUE;
bracket = (i == '[');
i = stdscan(NULL, &tokval);
if (i == TOKEN_SPECIAL) { /* check for address size override */
if (tasm_compatible_mode) {
switch ((int)tokval.t_integer) {
/* For TASM compatibility a size override inside the
* brackets changes the size of the operand, not the
* address type of the operand as it does in standard
* NASM syntax. Hence:
*
* mov eax,[DWORD val]
*
* is valid syntax in TASM compatibility mode. Note that
* you lose the ability to override the default address
* type for the instruction, but we never use anything
* but 32-bit flat model addressing in our code.
*/
case S_BYTE:
result->oprs[operand].type |= BITS8;
break;
case S_WORD:
result->oprs[operand].type |= BITS16;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].type |= BITS32;
break;
case S_QWORD:
result->oprs[operand].type |= BITS64;
break;
case S_TWORD:
result->oprs[operand].type |= BITS80;
break;
default:
error(ERR_NONFATAL,
"invalid operand size specification");
}
} else {
/* Standard NASM compatible syntax */
switch ((int)tokval.t_integer) {
case S_NOSPLIT:
result->oprs[operand].eaflags |= EAF_TIMESTWO;
break;
case S_BYTE:
result->oprs[operand].eaflags |= EAF_BYTEOFFS;
break;
case S_WORD:
result->oprs[operand].addr_size = 16;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].addr_size = 32;
result->oprs[operand].eaflags |= EAF_WORDOFFS;
break;
default:
error(ERR_NONFATAL, "invalid size specification in"
" effective address");
}
}
i = stdscan(NULL, &tokval);
}
} else { /* immediate operand, or register */
mref = FALSE;
bracket = FALSE; /* placate optimisers */
}
if ((result->oprs[operand].type & FAR) && !mref &&
result->opcode != I_JMP && result->opcode != I_CALL) {
error(ERR_NONFATAL, "invalid use of FAR operand specifier");
}
value = evaluate(stdscan, NULL, &tokval,
&result->oprs[operand].opflags,
critical, error, &hints);
i = tokval.t_type;
if (result->oprs[operand].opflags & OPFLAG_FORWARD) {
result->forw_ref = TRUE;
}
if (!value) { /* error in evaluator */
result->opcode = -1; /* unrecoverable parse error: */
return result; /* ignore this instruction */
}
if (i == ':' && mref) { /* it was seg:offset */
/*
* Process the segment override.
*/
if (value[1].type != 0 || value->value != 1 ||
REG_SREG & ~reg_flags[value->type])
error(ERR_NONFATAL, "invalid segment override");
else if (result->nprefix == MAXPREFIX)
error(ERR_NONFATAL,
"instruction has more than %d prefixes", MAXPREFIX);
else
result->prefixes[result->nprefix++] = value->type;
i = stdscan(NULL, &tokval); /* then skip the colon */
if (i == TOKEN_SPECIAL) { /* another check for size override */
switch ((int)tokval.t_integer) {
case S_WORD:
result->oprs[operand].addr_size = 16;
break;
case S_DWORD:
case S_LONG:
result->oprs[operand].addr_size = 32;
break;
default:
error(ERR_NONFATAL, "invalid size specification in"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -