📄 assemble.c
字号:
if (align < 0) align += wsize; isize += osize + align; } return isize * instruction->times; } if (instruction->opcode == I_INCBIN) { char fname[FILENAME_MAX]; FILE * fp; long len; char *prefix = "", *combine; char** pPrevPath = NULL; len = FILENAME_MAX-1; if (len > instruction->eops->stringlen) len = instruction->eops->stringlen; strncpy (fname, instruction->eops->stringval, len); fname[len] = '\0'; while (1) /* added by alexfru: 'incbin' uses include paths */ { combine = nasm_malloc(strlen(prefix) + len + 1); strcpy(combine, prefix); strcat(combine, fname); if ( (fp = fopen(combine, "rb")) != NULL) { nasm_free(combine); break; } nasm_free(combine); pPrevPath = pp_get_include_path_ptr (pPrevPath); if (pPrevPath == NULL) break; prefix = *pPrevPath; } if (fp == NULL) error (ERR_NONFATAL, "`incbin': unable to open file `%s'", fname); else if (fseek(fp, 0L, SEEK_END) < 0) error (ERR_NONFATAL, "`incbin': unable to seek on file `%s'", fname); else { len = ftell (fp); fclose (fp); if (instruction->eops->next) { len -= instruction->eops->next->offset; if (instruction->eops->next->next && len > instruction->eops->next->next->offset) { len = instruction->eops->next->next->offset; } } return instruction->times * len; } return 0; /* if we're here, there's an error */ } temp = nasm_instructions[instruction->opcode]; while (temp->opcode != -1) { int m = matches(temp, instruction); if (m == 99) m += jmp_match(segment, offset, bits, instruction, temp->code); if (m == 100) { /* we've matched an instruction. */ long isize; const char * codes = temp->code; int j; isize = calcsize(segment, offset, bits, instruction, codes); if (isize < 0) return -1; for (j = 0; j < instruction->nprefix; j++) { if ((instruction->prefixes[j] != P_A16 && instruction->prefixes[j] != P_O16 && bits==16) || (instruction->prefixes[j] != P_A32 && instruction->prefixes[j] != P_O32 && bits==32)) { isize++; } } return isize * instruction->times; } temp++; } return -1; /* didn't match any instruction */}/* check that opn[op] is a signed byte of size 16 or 32, and return the signed value*/static int is_sbyte (insn *ins, int op, int size){ signed long v; int ret; ret = !(ins->forw_ref && ins->oprs[op].opflags ) && /* dead in the water on forward reference or External */ optimizing>=0 && !(ins->oprs[op].type & STRICT) && ins->oprs[op].wrt==NO_SEG && ins->oprs[op].segment==NO_SEG; v = ins->oprs[op].offset; if (size==16) v = (signed short)v; /* sign extend if 16 bits */ return ret && v>=-128L && v<=127L;}static long calcsize (long segment, long offset, int bits, insn *ins, const char *codes) { long length = 0; unsigned char c; (void) segment; /* Don't warn that this parameter is unused */ (void) offset; /* Don't warn that this parameter is unused */ while (*codes) switch (c = *codes++) { case 01: case 02: case 03: codes += c, length += c; break; case 04: case 05: case 06: case 07: length++; break; case 010: case 011: case 012: codes++, length++; break; case 017: length++; break; case 014: case 015: case 016: length++; break; case 020: case 021: case 022: length++; break; case 024: case 025: case 026: length++; break; case 030: case 031: case 032: length += 2; break; case 034: case 035: case 036: if ( ins->oprs[c-034].type & (BITS16|BITS32) ) length += (ins->oprs[c-034].type & BITS16) ? 2 : 4; else length += (bits == 16) ? 2 : 4; break; case 037: length += 2; break; case 040: case 041: case 042: length += 4; break; case 044: case 045: case 046: length += ((ins->oprs[c-044].addr_size ? ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); break; case 050: case 051: case 052: length++; break; case 060: case 061: case 062: length += 2; break; case 064: case 065: case 066: if ( ins->oprs[c-064].type & (BITS16|BITS32) ) length += (ins->oprs[c-064].type & BITS16) ? 2 : 4; else length += (bits == 16) ? 2 : 4; break; case 070: case 071: case 072: length += 4; break; case 0130: case 0131: case 0132: length += is_sbyte(ins, c-0130, 16) ? 1 : 2; break; case 0133: case 0134: case 0135: codes+=2; length++; break; case 0140: case 0141: case 0142: length += is_sbyte(ins, c-0140, 32) ? 1 : 4; break; case 0143: case 0144: case 0145: codes+=2; length++; break; case 0300: case 0301: case 0302: length += chsize (&ins->oprs[c-0300], bits); break; case 0310: length += (bits==32); break; case 0311: length += (bits==16); break; case 0312: break; case 0320: length += (bits==32); break; case 0321: length += (bits==16); break; case 0322: break; case 0330: codes++, length++; break; case 0331: case 0332: break; case 0333: length++; break; case 0340: case 0341: case 0342: if (ins->oprs[0].segment != NO_SEG) errfunc (ERR_NONFATAL, "attempt to reserve non-constant" " quantity of BSS space"); else length += ins->oprs[0].offset << (c-0340); break; case 0370: case 0371: case 0372: break; case 0373: length++; break; default: /* can't do it by 'case' statements */ if (c>=0100 && c<=0277) { /* it's an EA */ ea ea_data; if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, 0, ins->forw_ref)) { errfunc (ERR_NONFATAL, "invalid effective address"); return -1; } else length += ea_data.size; } else errfunc (ERR_PANIC, "internal instruction table corrupt" ": instruction code 0x%02X given", c); } return length;}static void gencode (long segment, long offset, int bits, insn *ins, const char *codes, long insn_end) { static char condval[] = { /* conditional opcodes */ 0x7, 0x3, 0x2, 0x6, 0x2, 0x4, 0xF, 0xD, 0xC, 0xE, 0x6, 0x2, 0x3, 0x7, 0x3, 0x5, 0xE, 0xC, 0xD, 0xF, 0x1, 0xB, 0x9, 0x5, 0x0, 0xA, 0xA, 0xB, 0x8, 0x4 }; unsigned char c; unsigned char bytes[4]; long data, size; while (*codes) switch (c = *codes++) { case 01: case 02: case 03: out (offset, segment, codes, OUT_RAWDATA+c, NO_SEG, NO_SEG); codes += c; offset += c; break; case 04: case 06: switch (ins->oprs[0].basereg) { case R_CS: bytes[0] = 0x0E + (c == 0x04 ? 1 : 0); break; case R_DS: bytes[0] = 0x1E + (c == 0x04 ? 1 : 0); break; case R_ES: bytes[0] = 0x06 + (c == 0x04 ? 1 : 0); break; case R_SS: bytes[0] = 0x16 + (c == 0x04 ? 1 : 0); break; default: errfunc (ERR_PANIC, "bizarre 8086 segment register received"); } out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; break; case 05: case 07: switch (ins->oprs[0].basereg) { case R_FS: bytes[0] = 0xA0 + (c == 0x05 ? 1 : 0); break; case R_GS: bytes[0] = 0xA8 + (c == 0x05 ? 1 : 0); break; default: errfunc (ERR_PANIC, "bizarre 386 segment register received"); } out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; break; case 010: case 011: case 012: bytes[0] = *codes++ + regval(&ins->oprs[c-010]); out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset += 1; break; case 017: bytes[0] = 0; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset += 1; break; case 014: case 015: case 016: if (ins->oprs[c-014].offset < -128 || ins->oprs[c-014].offset > 127) { errfunc (ERR_WARNING, "signed byte value exceeds bounds"); } if (ins->oprs[c-014].segment != NO_SEG) { data = ins->oprs[c-014].offset; out (offset, segment, &data, OUT_ADDRESS+1, ins->oprs[c-014].segment, ins->oprs[c-014].wrt); } else { bytes[0] = ins->oprs[c-014].offset; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); } offset += 1; break; case 020: case 021: case 022: if (ins->oprs[c-020].offset < -256 || ins->oprs[c-020].offset > 255) { errfunc (ERR_WARNING, "byte value exceeds bounds"); } if (ins->oprs[c-020].segment != NO_SEG) { data = ins->oprs[c-020].offset; out (offset, segment, &data, OUT_ADDRESS+1, ins->oprs[c-020].segment, ins->oprs[c-020].wrt); } else { bytes[0] = ins->oprs[c-020].offset; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); } offset += 1; break; case 024: case 025: case 026: if (ins->oprs[c-024].offset < 0 || ins->oprs[c-024].offset > 255) errfunc (ERR_WARNING, "unsigned byte value exceeds bounds"); if (ins->oprs[c-024].segment != NO_SEG) { data = ins->oprs[c-024].offset; out (offset, segment, &data, OUT_ADDRESS+1, ins->oprs[c-024].segment, ins->oprs[c-024].wrt); } else { bytes[0] = ins->oprs[c-024].offset; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); } offset += 1; break; case 030: case 031: case 032: if (ins->oprs[c-030].segment == NO_SEG && ins->oprs[c-030].wrt == NO_SEG && (ins->oprs[c-030].offset < -65536L || ins->oprs[c-030].offset > 65535L)) { errfunc (ERR_WARNING, "word value exceeds bounds"); } data = ins->oprs[c-030].offset; out (offset, segment, &data, OUT_ADDRESS+2, ins->oprs[c-030].segment, ins->oprs[c-030].wrt); offset += 2; break; case 034: case 035: case 036: if ( ins->oprs[c-034].type & (BITS16|BITS32) ) size = (ins->oprs[c-034].type & BITS16) ? 2 : 4; else size = (bits == 16) ? 2 : 4; data = ins->oprs[c-034].offset; if (size==2 && (data < -65536L || data > 65535L)) errfunc (ERR_WARNING, "word value exceeds bounds"); out (offset, segment, &data, OUT_ADDRESS+size, ins->oprs[c-034].segment, ins->oprs[c-034].wrt); offset += size; break; case 037: if (ins->oprs[0].segment == NO_SEG) errfunc (ERR_NONFATAL, "value referenced by FAR is not" " relocatable"); data = 0L; out (offset, segment, &data, OUT_ADDRESS+2, outfmt->segbase(1+ins->oprs[0].segment), ins->oprs[0].wrt); offset += 2; break; case 040: case 041: case 042: data = ins->oprs[c-040].offset; out (offset, segment, &data, OUT_ADDRESS+4, ins->oprs[c-040].segment, ins->oprs[c-040].wrt); offset += 4; break; case 044: case 045: case 046: data = ins->oprs[c-044].offset; size = ((ins->oprs[c-044].addr_size ? ins->oprs[c-044].addr_size : bits) == 16 ? 2 : 4); if (size==2 && (data < -65536L || data > 65535L)) errfunc (ERR_WARNING, "word value exceeds bounds"); out (offset, segment, &data, OUT_ADDRESS+size, ins->oprs[c-044].segment, ins->oprs[c-044].wrt); offset += size; break; case 050: case 051: case 052: if (ins->oprs[c-050].segment != segment) errfunc (ERR_NONFATAL, "short relative jump outside segment"); data = ins->oprs[c-050].offset - insn_end; if (data > 127 || data < -128) errfunc (ERR_NONFATAL, "short jump is out of range"); bytes[0] = data; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset += 1; break; case 060: case 061: case 062: if (ins->oprs[c-060].segment != segment) { data = ins->oprs[c-060].offset; out (offset, segment, &data, OUT_REL2ADR+insn_end-offset, ins->oprs[c-060].segment, ins->oprs[c-060].wrt); } else { data = ins->oprs[c-060].offset - insn_end; out (offset, segment, &data, OUT_ADDRESS+2, NO_SEG, NO_SEG); } offset += 2; break; case 064: case 065: case 066: if ( ins->oprs[c-064].type & (BITS16|BITS32) ) size = (ins->oprs[c-064].type & BITS16) ? 2 : 4; else size = (bits == 16) ? 2 : 4; if (ins->oprs[c-064].segment != segment) { long reltype = (size == 2 ? OUT_REL2ADR : OUT_REL4ADR); data = ins->oprs[c-064].offset; out (offset, segment, &data, reltype+insn_end-offset, ins->oprs[c-064].segment, ins->oprs[c-064].wrt); } else { data = ins->oprs[c-064].offset - insn_end; out (offset, segment, &data, OUT_ADDRESS+size, NO_SEG, NO_SEG); } offset += size; break; case 070: case 071: case 072: if (ins->oprs[c-070].segment != segment) { data = ins->oprs[c-070].offset; out (offset, segment, &data, OUT_REL4ADR+insn_end-offset, ins->oprs[c-070].segment, ins->oprs[c-070].wrt); } else { data = ins->oprs[c-070].offset - insn_end; out (offset, segment, &data, OUT_ADDRESS+4, NO_SEG, NO_SEG); } offset += 4; break; case 0130: case 0131: case 0132: data = ins->oprs[c-0130].offset; if (is_sbyte(ins, c-0130, 16)) { bytes[0] = data; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; } else { if (ins->oprs[c-0130].segment == NO_SEG && ins->oprs[c-0130].wrt == NO_SEG && (data < -65536L || data > 65535L)) { errfunc (ERR_WARNING, "word value exceeds bounds"); } out (offset, segment, &data, OUT_ADDRESS+2, ins->oprs[c-0130].segment, ins->oprs[c-0130].wrt); offset += 2; } break; case 0133: case 0134: case 0135: codes++; bytes[0] = *codes++; if (is_sbyte(ins, c-0133, 16)) bytes[0] |= 2; /* s-bit */ out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; break; case 0140: case 0141: case 0142: data = ins->oprs[c-0140].offset; if (is_sbyte(ins, c-0140, 32)) { bytes[0] = data; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; } else { out (offset, segment, &data, OUT_ADDRESS+4, ins->oprs[c-0140].segment, ins->oprs[c-0140].wrt); offset += 4; } break; case 0143: case 0144: case 0145: codes++; bytes[0] = *codes++; if (is_sbyte(ins, c-0143, 32)) bytes[0] |= 2; /* s-bit */ out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset++; break; case 0300: case 0301: case 0302: if (chsize (&ins->oprs[c-0300], bits)) { *bytes = 0x67; out (offset, segment, bytes, OUT_RAWDATA+1, NO_SEG, NO_SEG); offset += 1; } else offset += 0; break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -