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

📄 assemble.c

📁 一个汇编语言编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	char  fname[FILENAME_MAX];
	FILE  * fp;
	long  len;

	len = FILENAME_MAX-1;
	if (len > instruction->eops->stringlen)
	    len = instruction->eops->stringlen;
	strncpy (fname, instruction->eops->stringval, len);
	fname[len] = '\0';
	if ( (fp = fopen(fname, "rb")) == 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) {
	if (matches(temp, instruction) == 100) {
	    /* we've matched an instruction. */
	    long  isize;
	    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 */
}

static long calcsize (long segment, long offset, int bits,
		      insn *ins, 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:
	length += ((ins->oprs[c-034].addr_size ?
		    ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4); break;
      case 037:
	length += 2; break;
      case 040: case 041: case 042:
	length += 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:
	length += ((ins->oprs[c-064].addr_size ?
		    ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4); break;
      case 070: case 071: case 072:
	length += 4; 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;
      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, 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:
	    data = ins->oprs[c-034].offset;
	    size = ((ins->oprs[c-034].addr_size ?
		     ins->oprs[c-034].addr_size : bits) == 16 ? 2 : 4);
	    if (size==16 && (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 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:
	    size = ((ins->oprs[c-064].addr_size ?
		     ins->oprs[c-064].addr_size : bits) == 16 ? 2 : 4);
	    if (ins->oprs[c-064].segment != segment) {
		data = ins->oprs[c-064].offset;
		size = (bits == 16 ? OUT_REL2ADR : OUT_REL4ADR);
		out (offset, segment, &data, size+insn_end-offset,
		     ins->oprs[c-064].segment, ins->oprs[c-064].wrt);
		size = (bits == 16 ? 2 : 4);
	    } 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 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;

	case 0310:
	    if (bits==32) {
		*bytes = 0x67;
		out (offset, segment, bytes,
		     OUT_RAWDATA+1, NO_SEG, NO_SEG);
		offset += 1;
	    } else
		offset += 0;
	    break;

	case 0311:
	    if (bits==16) {
		*bytes = 0x67;
		out (offset, segment, bytes,
		     OUT_RAWDATA+1, NO_SEG, NO_SEG);
		offset += 1;
	    } else
		offset += 0;
	    break;

	case 0312:
	    break;

	case 0320:
	    if (bits==32) {
		*bytes = 0x66;
		out (offset, segment, bytes,
		     OUT_RAWDATA+1, NO_SEG, NO_SEG);
		offset += 1;
	    } else
		offset += 0;
	    break;

	case 0321:
	    if (bits==16) {
		*bytes = 0x66;
		out (offset, segment, bytes,
		     OUT_RAWDATA+1, NO_SEG, NO_SEG);
		offset += 1;
	    } else
		offset += 0;
	    break;

	case 0322:
	    break;

	case 0330:
	    *bytes = *codes++ + condval[ins->condition];
	    out (offset, segment, bytes,
		 OUT_RAWDATA+1, NO_SEG, NO_SEG);
	    offset += 1;
	    break;

	case 0331:
	case 0332:
	    break;

	case 0333:
	    *bytes = 0xF3;
	    out (offset, segment, bytes,
		 OUT_RAWDATA+1, NO_SEG, NO_SEG);
	    offset += 1;
	    break;

	case 0340: case 0341: case 0342:
	    if (ins->oprs[0].segment != NO_SEG)
		errfunc (ERR_PANIC, "non-constant BSS size in pass two");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -