nasm.c
来自「开源的nasm编译器源码,研究编译器原理很有帮且」· C语言 代码 · 共 1,683 行 · 第 1/4 页
C
1,683 行
switch (i) { case 1: /* [SEGMENT n] */ seg = ofmt->section (value, pass2, &sb); if (seg == NO_SEG) { report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC, "segment name `%s' not recognised", value); } else { in_abs_seg = FALSE; location.segment = seg; } break; case 2: /* [EXTERN label:special] */ if (*value == '$') value++; /* skip initial $ if present */ if (pass0 == 2) { q = value; while (*q && *q != ':') q++; if (*q == ':') { *q++ = '\0'; ofmt->symdef(value, 0L, 0L, 3, q); } } else if (pass == 1) { /* pass == 1 */ q = value; validid = TRUE; if (!isidstart(*q)) validid = FALSE; while (*q && *q != ':') { if (!isidchar(*q)) validid = FALSE; q++; } if (!validid) { report_error (ERR_NONFATAL, "identifier expected after EXTERN"); break; } if (*q == ':') { *q++ = '\0'; special = q; } else special = NULL; if (!is_extern(value)) { /* allow re-EXTERN to be ignored */ int temp = pass0; pass0 = 1; /* fake pass 1 in labels.c */ declare_as_global (value, special, report_error); define_label (value, seg_alloc(), 0L, NULL, FALSE, TRUE, ofmt, report_error); pass0 = temp; } } /* else pass0 == 1 */ break; case 3: /* [BITS bits] */ sb = get_bits(value); break; case 4: /* [GLOBAL symbol:special] */ if (*value == '$') value++; /* skip initial $ if present */ if (pass0 == 2) { /* pass 2 */ q = value; while (*q && *q != ':') q++; if (*q == ':') { *q++ = '\0'; ofmt->symdef(value, 0L, 0L, 3, q); } } else if (pass2 == 1) { /* pass == 1 */ q = value; validid = TRUE; if (!isidstart(*q)) validid = FALSE; while (*q && *q != ':') { if (!isidchar(*q)) validid = FALSE; q++; } if (!validid) { report_error (ERR_NONFATAL, "identifier expected after GLOBAL"); break; } if (*q == ':') { *q++ = '\0'; special = q; } else special = NULL; declare_as_global (value, special, report_error); } /* pass == 1 */ break; case 5: /* [COMMON symbol size:special] */ if (*value == '$') value++; /* skip initial $ if present */ if (pass0 == 1) { p = value; validid = TRUE; if (!isidstart(*p)) validid = FALSE; while (*p && !isspace(*p)) { if (!isidchar(*p)) validid = FALSE; p++; } if (!validid) { report_error (ERR_NONFATAL, "identifier expected after COMMON"); break; } if (*p) { long size; while (*p && isspace(*p)) *p++ = '\0'; q = p; while (*q && *q != ':') q++; if (*q == ':') { *q++ = '\0'; special = q; } else special = NULL; size = readnum (p, &rn_error); if (rn_error) report_error (ERR_NONFATAL, "invalid size specified" " in COMMON declaration"); else define_common (value, seg_alloc(), size, special, ofmt, report_error); } else report_error (ERR_NONFATAL, "no size specified in" " COMMON declaration"); } else if (pass0 == 2) { /* pass == 2 */ 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 address] */ stdscan_reset(); stdscan_bufptr = value; tokval.t_type = TOKEN_INVALID; e = evaluate(stdscan, NULL, &tokval, NULL, pass2, report_error, NULL); if (e) { if (!is_reloc(e)) report_error (pass0==1 ? ERR_NONFATAL : ERR_PANIC, "cannot use non-relocatable expression as " "ABSOLUTE address"); else { abs_seg = reloc_seg(e); abs_offset = reloc_value(e); } } else if (pass==1) abs_offset = 0x100;/* don't go near zero in case of / */ else report_error (ERR_PANIC, "invalid ABSOLUTE address " "in pass two"); in_abs_seg = TRUE; location.segment = NO_SEG; break; case 7: /* DEBUG */ 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 (pass==1 ? ERR_NONFATAL : ERR_PANIC, "identifier expected after DEBUG"); break; } while (*p && isspace(*p)) p++; if (pass==pass_max) ofmt->current_dfmt->debug_directive (debugid, p); break; case 8: /* [WARNING {+|-}warn-name] */ if (pass1 == 1) { while (*value && isspace(*value)) value++; if (*value == '+' || *value == '-') { validid = (*value == '-') ? TRUE : FALSE; value++; } else validid = FALSE; for (i=1; i<=ERR_WARN_MAX; i++) if (!nasm_stricmp(value, suppressed_names[i])) break; if (i <= ERR_WARN_MAX) suppressed[i] = validid; else report_error (ERR_NONFATAL, "invalid warning id in WARNING directive"); } break; case 9: /* cpu */ cpu = get_cpu (value); break; case 10: /* fbk 9/2/00 */ /* [LIST {+|-}] */ while (*value && isspace(*value)) value++; if (*value == '+') { user_nolist = 0; } else { if (*value == '-') { user_nolist = 1; } else { report_error (ERR_NONFATAL, "invalid parameter to \"list\" directive"); } } break; default: if (!ofmt->directive (directive, value, pass2)) report_error (pass1==1 ? ERR_NONFATAL : ERR_PANIC, "unrecognised directive [%s]", directive); } } else /* it isn't a directive */ { parse_line (pass1, line, &output_ins, report_error, evaluate, def_label); if (!(optimizing>0) && pass == 2) { 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; } if (!(optimizing>0) && output_ins.forw_ref) { if (pass == 1) { for(i = 0; i < output_ins.operands; i++) { if (output_ins.oprs[i].opflags & OPFLAG_FORWARD) { struct forwrefinfo *fwinf = (struct forwrefinfo *)saa_wstruct(forwrefs); fwinf->lineno = globallineno; fwinf->operand = i; } } } else { /* pass == 2 */ /* * 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.operands >= 2 && (output_ins.oprs[1].opflags & OPFLAG_FORWARD)) { output_ins.oprs[1].type &= ~(ONENESS|BYTENESS); } } /* pass == 2 */ } /* forw_ref */ if (output_ins.opcode == I_EQU) { if (pass1 == 1) { /* * Special `..' EQUs get processed in pass two, * except `..@' macro-processor EQUs which are done * in the normal place. */ if (!output_ins.label) report_error (ERR_NONFATAL, "EQU not preceded by label"); else if (output_ins.label[0] != '.' || output_ins.label[1] != '.' || output_ins.label[2] == '@') { if (output_ins.operands == 1 && (output_ins.oprs[0].type & IMMEDIATE) && output_ins.oprs[0].wrt == NO_SEG) { int isext = output_ins.oprs[0].opflags & OPFLAG_EXTERN; def_label (output_ins.label, output_ins.oprs[0].segment, output_ins.oprs[0].offset, NULL, FALSE, isext, 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[0].wrt == NO_SEG && (output_ins.oprs[1].type & IMMEDIATE) && output_ins.oprs[1].segment == NO_SEG && output_ins.oprs[1].wrt == NO_SEG) { def_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 { /* pass == 2 */ /* * 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"); } } /* pass == 2 */ } else { /* instruction isn't an EQU */ if (pass1 == 1) { long 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 */ long 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_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; default: typeinfo = TY_LABEL; } ofmt->current_dfmt->debug_typevalue(typeinfo); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?