⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nasm.c

📁 一个汇编语言编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		/* 
		 * 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, &currentfile);
	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 + -