📄 nasm.c
字号:
&& (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");
}
}
} else { /* instruction isn't an EQU */
if (pass1 == 1) {
int64_t l = insn_size(location.segment, offs, sb, cpu,
&output_ins, report_error);
/* if (using_debug_info) && output_ins.opcode != -1) */
if (using_debug_info)
{ /* fbk 03/25/01 */
/* this is done here so we can do debug type info */
int32_t typeinfo =
TYS_ELEMENTS(output_ins.operands);
switch (output_ins.opcode) {
case I_RESB:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_BYTE;
break;
case I_RESW:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_WORD;
break;
case I_RESD:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_DWORD;
break;
case I_RESQ:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_QWORD;
break;
case I_REST:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_TBYTE;
break;
case I_RESO:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_OWORD;
break;
case I_RESY:
typeinfo =
TYS_ELEMENTS(output_ins.oprs[0].
offset) | TY_YWORD;
break;
case I_DB:
typeinfo |= TY_BYTE;
break;
case I_DW:
typeinfo |= TY_WORD;
break;
case I_DD:
if (output_ins.eops_float)
typeinfo |= TY_FLOAT;
else
typeinfo |= TY_DWORD;
break;
case I_DQ:
typeinfo |= TY_QWORD;
break;
case I_DT:
typeinfo |= TY_TBYTE;
break;
case I_DO:
typeinfo |= TY_OWORD;
break;
case I_DY:
typeinfo |= TY_YWORD;
break;
default:
typeinfo = TY_LABEL;
}
ofmt->current_dfmt->debug_typevalue(typeinfo);
}
if (l != -1) {
offs += l;
SET_CURR_OFFS(offs);
}
/*
* else l == -1 => invalid instruction, which will be
* flagged as an error on pass 2
*/
} else {
offs += assemble(location.segment, offs, sb, cpu,
&output_ins, ofmt, report_error,
&nasmlist);
SET_CURR_OFFS(offs);
}
} /* not an EQU */
cleanup_insn(&output_ins);
}
nasm_free(line);
location.offset = offs = GET_CURR_OFFS;
} /* end while (line = preproc->getline... */
if (pass1 == 2 && global_offset_changed)
report_error(ERR_NONFATAL,
"phase error detected at end of assembly.");
if (pass1 == 1)
preproc->cleanup(1);
if (pass1 == 1 && terminate_after_phase) {
fclose(ofile);
remove(outname);
if (want_usage)
usage();
exit(1);
}
if (passn > 1 && !global_offset_changed)
pass0++;
else if (global_offset_changed && global_offset_changed < prev_offset_changed) {
prev_offset_changed = global_offset_changed;
stall_count = 0;
}
else stall_count++;
if((stall_count > 997) || (passn >= pass_max))
/* We get here if the labels don't converge
* Example: FOO equ FOO + 1
*/
report_error(ERR_NONFATAL,
"Can't find valid values for all labels "
"after %d passes, giving up.\n"
" Possible cause: recursive equ's.", passn);
}
preproc->cleanup(0);
nasmlist.cleanup();
if (opt_verbose_info) /* -On and -Ov switches */
fprintf(stdout,
"info:: assembly required 1+%d+1 passes\n", passn-3);
} /* exit from assemble_file (...) */
static enum directives getkw(char **directive, char **value)
{
char *p, *q, *buf;
buf = *directive;
/* allow leading spaces or tabs */
while (*buf == ' ' || *buf == '\t')
buf++;
if (*buf != '[')
return 0;
p = buf;
while (*p && *p != ']')
p++;
if (!*p)
return 0;
q = p++;
while (*p && *p != ';') {
if (!nasm_isspace(*p))
return 0;
p++;
}
q[1] = '\0';
*directive = p = buf + 1;
while (*buf && *buf != ' ' && *buf != ']' && *buf != '\t')
buf++;
if (*buf == ']') {
*buf = '\0';
*value = buf;
} else {
*buf++ = '\0';
while (nasm_isspace(*buf))
buf++; /* beppu - skip leading whitespace */
*value = buf;
while (*buf != ']')
buf++;
*buf++ = '\0';
}
return bsii(*directive, directives, elements(directives));
}
/**
* gnu style error reporting
* This function prints an error message to error_file in the
* style used by GNU. An example would be:
* file.asm:50: error: blah blah blah
* where file.asm is the name of the file, 50 is the line number on
* which the error occurs (or is detected) and "error:" is one of
* the possible optional diagnostics -- it can be "error" or "warning"
* or something else. Finally the line terminates with the actual
* error message.
*
* @param severity the severity of the warning or error
* @param fmt the printf style format string
*/
static void report_error_gnu(int severity, const char *fmt, ...)
{
va_list ap;
if (is_suppressed_warning(severity))
return;
if (severity & ERR_NOFILE)
fputs("nasm: ", error_file);
else {
char *currentfile = NULL;
int32_t lineno = 0;
src_get(&lineno, ¤tfile);
fprintf(error_file, "%s:%"PRId32": ", currentfile, lineno);
nasm_free(currentfile);
}
va_start(ap, fmt);
report_error_common(severity, fmt, ap);
va_end(ap);
}
/**
* MS style error reporting
* This function prints an error message to error_file in the
* style used by Visual C and some other Microsoft tools. An example
* would be:
* file.asm(50) : error: blah blah blah
* where file.asm is the name of the file, 50 is the line number on
* which the error occurs (or is detected) and "error:" is one of
* the possible optional diagnostics -- it can be "error" or "warning"
* or something else. Finally the line terminates with the actual
* error message.
*
* @param severity the severity of the warning or error
* @param fmt the printf style format string
*/
static void report_error_vc(int severity, const char *fmt, ...)
{
va_list ap;
if (is_suppressed_warning(severity))
return;
if (severity & ERR_NOFILE)
fputs("nasm: ", error_file);
else {
char *currentfile = NULL;
int32_t lineno = 0;
src_get(&lineno, ¤tfile);
fprintf(error_file, "%s(%"PRId32") : ", currentfile, lineno);
nasm_free(currentfile);
}
va_start(ap, fmt);
report_error_common(severity, fmt, ap);
va_end(ap);
}
/**
* check for supressed warning
* checks for suppressed warning or pass one only warning and we're
* not in pass 1
*
* @param severity the severity of the warning or error
* @return true if we should abort error/warning printing
*/
static bool is_suppressed_warning(int severity)
{
/*
* See if it's a suppressed warning.
*/
return (severity & ERR_MASK) == ERR_WARNING &&
(((severity & ERR_WARN_MASK) != 0 &&
!warning_on[(severity & ERR_WARN_MASK) >> ERR_WARN_SHR]) ||
/* See if it's a pass-one only warning and we're not in pass one. */
((severity & ERR_PASS1) && pass0 != 1) ||
((severity & ERR_PASS2) && pass0 != 2));
}
/**
* common error reporting
* This is the common back end of the error reporting schemes currently
* implemented. It prints the nature of the warning and then the
* specific error message to error_file and may or may not return. It
* doesn't return if the error severity is a "panic" or "debug" type.
*
* @param severity the severity of the warning or error
* @param fmt the printf style format string
*/
static void report_error_common(int severity, const char *fmt,
va_list args)
{
switch (severity & (ERR_MASK|ERR_NO_SEVERITY)) {
case ERR_WARNING:
fputs("warning: ", error_file);
break;
case ERR_NONFATAL:
fputs("error: ", error_file);
break;
case ERR_FATAL:
fputs("fatal: ", error_file);
break;
case ERR_PANIC:
fputs("panic: ", error_file);
break;
case ERR_DEBUG:
fputs("debug: ", error_file);
break;
default:
break;
}
vfprintf(error_file, fmt, args);
putc('\n', error_file);
if (severity & ERR_USAGE)
want_usage = true;
switch (severity & ERR_MASK) {
case ERR_DEBUG:
/* no further action, by definition */
break;
case ERR_WARNING:
if (warning_on[0]) /* Treat warnings as errors */
terminate_after_phase = true;
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 */
exit(3);
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 int32_t no_pp_lineinc;
static void no_pp_reset(char *file, int pass, efunc error, evalfunc eval,
ListGen * listgen, StrList **deplist)
{
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -