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

📄 assemble.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	    long insn_size = calcsize(segment, offset, bits,
				      instruction, codes);
	    itimes = instruction->times;
	    if (insn_size < 0)	       /* shouldn't be, on pass two */
	    	error (ERR_PANIC, "errors made it through from pass one");
	    else while (itimes--) {
		for (j=0; j<instruction->nprefix; j++) {
		    unsigned char c=0;
		    switch (instruction->prefixes[j]) {
		      case P_LOCK:
			c = 0xF0; break;
		      case P_REPNE: case P_REPNZ:
			c = 0xF2; break;
		      case P_REPE: case P_REPZ: case P_REP:
			c = 0xF3; break;
		      case R_CS: c = 0x2E; break;
		      case R_DS: c = 0x3E; break;
		      case R_ES: c = 0x26; break;
		      case R_FS: c = 0x64; break;
		      case R_GS: c = 0x65; break;
		      case R_SS: c = 0x36; break;
		      case R_SEGR6:
		      case R_SEGR7:
			error (ERR_NONFATAL, "segr6 and segr7 cannot be used as prefixes");
			break;
		      case P_A16:
			if (bits != 16)
			    c = 0x67;
			break;
		      case P_A32:
			if (bits != 32)
			    c = 0x67;
			break;
		      case P_O16:
			if (bits != 16)
			    c = 0x66;
			break;
		      case P_O32:
			if (bits != 32)
			    c = 0x66;
			break;
		      default:
			error (ERR_PANIC,
			       "invalid instruction prefix");
		    }
		    if (c != 0) {
			out (offset, segment, &c, OUT_RAWDATA+1,
			     NO_SEG, NO_SEG);
			offset++;
		    }
		}
		insn_end = offset + insn_size;
		gencode (segment, offset, bits, instruction, codes, insn_end);
		offset += insn_size;
		if (itimes > 0 && itimes == instruction->times-1) {
		    /*
		     * Dummy call to list->output to give the offset to the
		     * listing module.
		     */
		    list->output (offset, NULL, OUT_RAWDATA);
		    list->uplevel (LIST_TIMES);
		}
	    }
	    if (instruction->times > 1)
		list->downlevel (LIST_TIMES);
	    return offset - start;
	} else if (m > 0  &&  m > size_prob) {
	    size_prob = m;
	}
	temp++;
    }

    if (temp->opcode == -1) {	       /* didn't match any instruction */
	if (size_prob == 1)	       /* would have matched, but for size */
	    error (ERR_NONFATAL, "operation size not specified");
	else if (size_prob == 2)
	    error (ERR_NONFATAL, "mismatch in operand sizes");
	else if (size_prob == 3)
	    error (ERR_NONFATAL, "no instruction for this cpu level");
	else
	    error (ERR_NONFATAL,
		   "invalid combination of opcode and operands");
    }
    return 0;
}

long insn_size (long segment, long offset, int bits, unsigned long cp,
		insn *instruction, efunc error) 
{
    struct itemplate *temp;

    errfunc = error;		       /* to pass to other functions */
    cpu = cp;

    if (instruction->opcode == -1)
    	return 0;

    if (instruction->opcode == I_DB ||
	instruction->opcode == I_DW ||
	instruction->opcode == I_DD ||
	instruction->opcode == I_DQ ||
	instruction->opcode == I_DT) 
    {
	extop *e;
	long isize, osize, wsize = 0;  /* placate gcc */

	isize = 0;
	switch (instruction->opcode) 
	{
	  case I_DB: wsize = 1; break;
	  case I_DW: wsize = 2; break;
	  case I_DD: wsize = 4; break;
	  case I_DQ: wsize = 8; break;
	  case I_DT: wsize = 10; break;
	}

	for (e = instruction->eops; e; e = e->next) 
	{
	    long align;

	    osize = 0;
	    if (e->type == EOT_DB_NUMBER)
		osize = 1;
	    else if (e->type == EOT_DB_STRING)
		osize = e->stringlen;

	    align = (-osize) % wsize;
	    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: 

⌨️ 快捷键说明

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