📄 nasm.c
字号:
/*
* else l == -1 => invalid instruction, which will be
* flagged as an error on pass 2
*/
}
cleanup_insn (&output_ins);
}
nasm_free (line);
location.offset = offs = get_curr_ofs;
}
preproc->cleanup();
if (terminate_after_phase) {
fclose(ofile);
remove(outname);
if (want_usage)
usage();
exit (1);
}
/*
* pass two
*/
pass = 2;
saa_rewind (forwrefs);
if (*listname)
nasmlist.init(listname, report_error);
forwref = saa_rstruct (forwrefs);
in_abs_seg = FALSE;
location.segment = ofmt->section(NULL, pass, &sb);
raa_free (offsets);
offsets = raa_init();
preproc->reset(fname, 2, report_error, evaluate, &nasmlist);
globallineno = 0;
location.offset = offs = get_curr_ofs;
while ( (line = preproc->getline()) )
{
globallineno++;
/* here we parse our directives; this is not handled by
* the 'real' parser. */
if ( (i = getkw (line, &value)) ) {
switch (i) {
case 1: /* [SEGMENT n] */
seg = ofmt->section (value, pass, &sb);
if (seg == NO_SEG) {
report_error (ERR_PANIC,
"invalid segment name on pass two");
} else
in_abs_seg = FALSE;
location.segment = seg;
break;
case 2: /* [EXTERN label] */
q = value;
while (*q && *q != ':')
q++;
if (*q == ':') {
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
break;
case 3: /* [BITS bits] */
switch (atoi(value)) {
case 16:
case 32:
sb = atoi(value);
break;
default:
report_error(ERR_PANIC,
"invalid [BITS] value on pass two",
value);
break;
}
break;
case 4: /* [GLOBAL symbol] */
q = value;
while (*q && *q != ':')
q++;
if (*q == ':') {
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
break;
case 5: /* [COMMON symbol size] */
q = value;
while (*q && *q != ':') {
if (isspace(*q))
*q = '\0';
q++;
}
if (*q == ':') {
*q++ = '\0';
ofmt->symdef(value, 0L, 0L, 3, q);
}
break;
case 6: /* [ABSOLUTE addr] */
stdscan_reset();
stdscan_bufptr = value;
tokval.t_type = TOKEN_INVALID;
e = evaluate(stdscan, NULL, &tokval, NULL, 2, report_error,
NULL);
if (e) {
if (!is_reloc(e))
report_error (ERR_PANIC, "non-reloc ABSOLUTE address"
" in pass two");
else {
abs_seg = reloc_seg(e);
abs_offset = reloc_value(e);
}
} else
report_error (ERR_PANIC, "invalid ABSOLUTE address "
"in pass two");
in_abs_seg = TRUE;
location.segment = abs_seg;
break;
case 7:
p = value;
q = debugid;
validid = TRUE;
if (!isidstart(*p))
validid = FALSE;
while (*p && !isspace(*p)) {
if (!isidchar(*p))
validid = FALSE;
*q++ = *p++;
}
*q++ = 0;
if (!validid) {
report_error (ERR_PANIC,
"identifier expected after DEBUG in pass 2");
break;
}
while (*p && isspace(*p))
p++;
ofmt->current_dfmt->debug_directive (debugid, p);
break;
default:
if (!ofmt->directive (line+1, value, 2))
report_error (ERR_PANIC, "invalid directive on pass two");
break;
}
}
else /* not a directive */
{
parse_line (2, line, &output_ins,
report_error, evaluate, redefine_label);
if (forwref != NULL && globallineno == forwref->lineno) {
output_ins.forw_ref = TRUE;
do {
output_ins.oprs[forwref->operand].opflags|= OPFLAG_FORWARD;
forwref = saa_rstruct (forwrefs);
} while (forwref != NULL && forwref->lineno == globallineno);
} else
output_ins.forw_ref = FALSE;
/*
* Hack to prevent phase error in the code
* rol ax,x
* x equ 1
*
* If the second operand is a forward reference,
* the UNITY property of the number 1 in that
* operand is cancelled. Otherwise the above
* sequence will cause a phase error.
*
* This hack means that the above code will
* generate 286+ code.
*
* The forward reference will mean that the
* operand will not have the UNITY property on
* the first pass, so the pass behaviours will
* be consistent.
*/
if (output_ins.forw_ref &&
output_ins.operands >= 2 &&
(output_ins.oprs[1].opflags & OPFLAG_FORWARD))
{
output_ins.oprs[1].type &= ~ONENESS;
}
if (output_ins.opcode == I_EQU)
{
/*
* Special `..' EQUs get processed here, except
* `..@' macro processor EQUs which are done above.
*/
if (output_ins.label[0] == '.' &&
output_ins.label[1] == '.' &&
output_ins.label[2] != '@')
{
if (output_ins.operands == 1 &&
(output_ins.oprs[0].type & IMMEDIATE)) {
define_label (output_ins.label,
output_ins.oprs[0].segment,
output_ins.oprs[0].offset,
NULL, FALSE, FALSE, ofmt, report_error);
}
else if (output_ins.operands == 2 &&
(output_ins.oprs[0].type & IMMEDIATE) &&
(output_ins.oprs[0].type & COLON) &&
output_ins.oprs[0].segment == NO_SEG &&
(output_ins.oprs[1].type & IMMEDIATE) &&
output_ins.oprs[1].segment == NO_SEG)
{
define_label (output_ins.label,
output_ins.oprs[0].offset | SEG_ABS,
output_ins.oprs[1].offset,
NULL, FALSE, FALSE, ofmt, report_error);
}
else
report_error(ERR_NONFATAL, "bad syntax for EQU");
}
}
offs += assemble (location.segment, offs, sb,
&output_ins, ofmt, report_error, &nasmlist);
cleanup_insn (&output_ins);
set_curr_ofs (offs);
}
nasm_free (line);
location.offset = offs = get_curr_ofs;
}
preproc->cleanup();
nasmlist.cleanup();
}
static int getkw (char *buf, char **value)
{
char *p, *q;
if (*buf!='[')
return 0;
p = buf;
while (*p && *p != ']') p++;
if (!*p)
return 0;
q = p++;
while (*p && *p != ';') {
if (!isspace(*p))
return 0;
p++;
}
q[1] = '\0';
p = buf+1;
while (*buf && *buf!=' ' && *buf!=']' && *buf!='\t')
buf++;
if (*buf==']') {
*buf = '\0';
*value = buf;
} else {
*buf++ = '\0';
while (isspace(*buf)) buf++; /* beppu - skip leading whitespace */
*value = buf;
while (*buf!=']') buf++;
*buf++ = '\0';
}
for (q=p; *q; q++)
*q = tolower(*q);
if (!strcmp(p, "segment") || !strcmp(p, "section"))
return 1;
if (!strcmp(p, "extern"))
return 2;
if (!strcmp(p, "bits"))
return 3;
if (!strcmp(p, "global"))
return 4;
if (!strcmp(p, "common"))
return 5;
if (!strcmp(p, "absolute"))
return 6;
if (!strcmp(p, "debug"))
return 7;
return -1;
}
static void report_error (int severity, char *fmt, ...)
{
va_list ap;
/*
* See if it's a suppressed warning.
*/
if ((severity & ERR_MASK) == ERR_WARNING &&
(severity & ERR_WARN_MASK) != 0 &&
suppressed[ (severity & ERR_WARN_MASK) >> ERR_WARN_SHR ])
return; /* and bail out if so */
/*
* See if it's a pass-one only warning and we're not in pass one.
*/
if ((severity & ERR_PASS1) && pass != 1)
return;
if (severity & ERR_NOFILE)
fputs ("nasm: ", error_file);
else {
char * currentfile = NULL;
long lineno = 0;
src_get (&lineno, ¤tfile);
fprintf (error_file, "%s:%ld: ", currentfile, lineno);
nasm_free (currentfile);
}
if ( (severity & ERR_MASK) == ERR_WARNING)
fputs ("warning: ", error_file);
else if ( (severity & ERR_MASK) == ERR_PANIC)
fputs ("panic: ", error_file);
va_start (ap, fmt);
vfprintf (error_file, fmt, ap);
fputc ('\n', error_file);
if (severity & ERR_USAGE)
want_usage = TRUE;
switch (severity & ERR_MASK) {
case ERR_WARNING:
/* no further action, by definition */
break;
case ERR_NONFATAL:
terminate_after_phase = TRUE;
break;
case ERR_FATAL:
if (ofile) {
fclose(ofile);
remove(outname);
}
if (want_usage)
usage();
exit(1); /* instantly die */
break; /* placate silly compilers */
case ERR_PANIC:
fflush(NULL);
abort(); /* halt, catch fire, and dump core */
break;
}
}
static void usage(void)
{
fputs("type `nasm -h' for help\n", error_file);
}
static void register_output_formats(void)
{
ofmt = ofmt_register (report_error);
}
#define BUF_DELTA 512
static FILE *no_pp_fp;
static efunc no_pp_err;
static ListGen *no_pp_list;
static long no_pp_lineinc;
static void no_pp_reset (char *file, int pass, efunc error, evalfunc eval,
ListGen *listgen)
{
src_set_fname(nasm_strdup(file));
src_set_linnum(0);
no_pp_lineinc = 1;
no_pp_err = error;
no_pp_fp = fopen(file, "r");
if (!no_pp_fp)
no_pp_err (ERR_FATAL | ERR_NOFILE,
"unable to open input file `%s'", file);
no_pp_list = listgen;
(void) pass; /* placate compilers */
(void) eval; /* placate compilers */
}
static char *no_pp_getline (void)
{
char *buffer, *p, *q;
int bufsize;
bufsize = BUF_DELTA;
buffer = nasm_malloc(BUF_DELTA);
src_set_linnum(src_get_linnum() + no_pp_lineinc);
while (1) { /* Loop to handle %line */
p = buffer;
while (1) { /* Loop to handle long lines */
q = fgets(p, bufsize-(p-buffer), no_pp_fp);
if (!q)
break;
p += strlen(p);
if (p > buffer && p[-1] == '\n')
break;
if (p-buffer > bufsize-10) {
int offset;
offset = p - buffer;
bufsize += BUF_DELTA;
buffer = nasm_realloc(buffer, bufsize);
p = buffer + offset;
}
}
if (!q && p == buffer) {
nasm_free (buffer);
return NULL;
}
/*
* Play safe: remove CRs, LFs and any spurious ^Zs, if any of
* them are present at the end of the line.
*/
buffer[strcspn(buffer, "\r\n\032")] = '\0';
if (!strncmp(buffer, "%line", 5)) {
long ln;
int li;
char *nm = nasm_malloc(strlen(buffer));
if (sscanf(buffer+5, "%ld+%d %s", &ln, &li, nm) == 3) {
nasm_free( src_set_fname(nm) );
src_set_linnum(ln);
no_pp_lineinc = li;
continue;
}
nasm_free(nm);
}
break;
}
no_pp_list->line (LIST_READ, buffer);
return buffer;
}
static void no_pp_cleanup (void)
{
fclose(no_pp_fp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -