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

📄 assemble.c

📁 一个免费的汇编语言编译器的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		    break;
		case 2:
		case 4:
		    data = ins->oprs[(c>>3)&7].offset;
		    out (offset, segment, &data,
			 OUT_ADDRESS+ea_data.bytes,
			 ins->oprs[(c>>3)&7].segment, ins->oprs[(c>>3)&7].wrt);
		    s += ea_data.bytes;
		    break;
		}
		offset += s;
	    } else
		errfunc (ERR_PANIC, "internal instruction table corrupt"
		     ": instruction code 0x%02X given", c);
	}
}

#include "regvals.c"

static int regval (operand *o) 
{
    if ( o->basereg < EXPR_REG_START || o->basereg >= REG_ENUM_LIMIT ) {
	errfunc (ERR_PANIC, "invalid operand passed to regval()");
    }
    return regvals[o->basereg];
}

static int matches (struct itemplate *itemp, insn *instruction) 
{
    int i, size[3], asize, oprs, ret;

    ret = 100;

    /*
     * Check the opcode
     */
    if (itemp->opcode != instruction->opcode) return 0;

    /*
     * Count the operands
     */
    if (itemp->operands != instruction->operands) return 0;

    /*
     * Check that no spurious colons or TOs are present
     */
    for (i=0; i<itemp->operands; i++)
	if (instruction->oprs[i].type & ~itemp->opd[i] & (COLON|TO))
	    return 0;

    /*
     * Check that the operand flags all match up
     */
    for (i=0; i<itemp->operands; i++)
	if (itemp->opd[i] & ~instruction->oprs[i].type ||
	    ((itemp->opd[i] & SIZE_MASK) &&
	     ((itemp->opd[i] ^ instruction->oprs[i].type) & SIZE_MASK)))
	{
	    if ((itemp->opd[i] & ~instruction->oprs[i].type & NON_SIZE) ||
		(instruction->oprs[i].type & SIZE_MASK))
		return 0;
	    else
/*		ret = 1;   */
		return 1;
	}

    /*
     * Check operand sizes
     */
    if (itemp->flags & IF_ARMASK) {
      size[0] = size[1] = size[2] = 0;

      switch (itemp->flags & IF_ARMASK) {
      case IF_AR0: i = 0; break;
      case IF_AR1: i = 1; break;
      case IF_AR2: i = 2; break;
      default:     break;	/* Shouldn't happen */
      }
      if (itemp->flags & IF_SB) {
	size[i] = BITS8;
      } else if (itemp->flags & IF_SW) {
	size[i] = BITS16;
      } else if (itemp->flags & IF_SD) {
	size[i] = BITS32;
      }
    } else {
      asize = 0;
      if (itemp->flags & IF_SB) {
	asize = BITS8;
	oprs = itemp->operands;
      } else if (itemp->flags & IF_SW) {
	asize = BITS16;
	oprs = itemp->operands;
      } else if (itemp->flags & IF_SD) {
	asize = BITS32;
	oprs = itemp->operands;
      }
      size[0] = size[1] = size[2] = asize;
    }

    if (itemp->flags & (IF_SM | IF_SM2)) {
      oprs = (itemp->flags & IF_SM2 ? 2 : itemp->operands);
      asize = 0;
      for (i=0; i<oprs; i++) {
	if ( (asize = itemp->opd[i] & SIZE_MASK) != 0) {
	  int j;
	  for (j=0; j<oprs; j++)
	    size[j] = asize;
	  break;
	}
      }
    } else {
      oprs = itemp->operands;
    }

    for (i=0; i<itemp->operands; i++)
	if (!(itemp->opd[i] & SIZE_MASK) &&
	    (instruction->oprs[i].type & SIZE_MASK & ~size[i]))
/*	    ret = 2;  */
	    return 2;

    /*
     * Check template is okay at the set cpu level
     */
    if ((itemp->flags & IF_PLEVEL) > cpu) return 3;
    
    /*
     * Check if special handling needed for Jumps
     */
    if ((unsigned char)(itemp->code[0]) >= 0370) return 99;
     
    return ret;
}

static ea *process_ea (operand *input, ea *output, int addrbits, int rfield,
		       int forw_ref) 
{
    if (!(REGISTER & ~input->type)) {  /* it's a single register */
	static int regs[] = {
	  R_AL,   R_CL,   R_DL,   R_BL,   R_AH,   R_CH,   R_DH,   R_BH,
	  R_AX,   R_CX,   R_DX,   R_BX,   R_SP,   R_BP,   R_SI,   R_DI,
	  R_EAX,  R_ECX,  R_EDX,  R_EBX,  R_ESP,  R_EBP,  R_ESI,  R_EDI,
	  R_MM0,  R_MM1,  R_MM2,  R_MM3,  R_MM4,  R_MM5,  R_MM6,  R_MM7,
	  R_XMM0, R_XMM1, R_XMM2, R_XMM3, R_XMM4, R_XMM5, R_XMM6, R_XMM7
	};
	int i;

	for (i=0; i<elements(regs); i++)
	    if (input->basereg == regs[i]) break;
	if (i<elements(regs)) {
	    output->sib_present = FALSE;/* no SIB necessary */
	    output->bytes = 0;	       /* no offset necessary either */
            output->modrm = 0xC0 | (rfield << 3) | (i & 7);
	} 
	else
	    return NULL;
    } else {			       /* it's a memory reference */
	if (input->basereg==-1 && (input->indexreg==-1 || input->scale==0)) {
	    /* it's a pure offset */
	    if (input->addr_size)
		addrbits = input->addr_size;
	    output->sib_present = FALSE;
	    output->bytes = (addrbits==32 ? 4 : 2);
	    output->modrm = (addrbits==32 ? 5 : 6) | (rfield << 3);
	} 
	else {		       /* it's an indirection */
	    int i=input->indexreg, b=input->basereg, s=input->scale;
	    long o=input->offset, seg=input->segment;
	    int hb=input->hintbase, ht=input->hinttype;
	    int t;

	    if (s==0) i = -1;	       /* make this easy, at least */

	    if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
		|| i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
		|| b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
		|| b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI) {
		/* it must be a 32-bit memory reference. Firstly we have
		 * to check that all registers involved are type Exx. */
		if (i!=-1 && i!=R_EAX && i!=R_EBX && i!=R_ECX && i!=R_EDX
		    && i!=R_EBP && i!=R_ESP && i!=R_ESI && i!=R_EDI)
		    return NULL;
		if (b!=-1 && b!=R_EAX && b!=R_EBX && b!=R_ECX && b!=R_EDX
		    && b!=R_EBP && b!=R_ESP && b!=R_ESI && b!=R_EDI)
		    return NULL;

		/* While we're here, ensure the user didn't specify WORD. */
		if (input->addr_size == 16)
		    return NULL;

		/* now reorganise base/index */
		if (s == 1 && b != i && b != -1 && i != -1 &&
		    ((hb==b&&ht==EAH_NOTBASE) || (hb==i&&ht==EAH_MAKEBASE)))
		    t = b, b = i, i = t;   /* swap if hints say so */
		if (b==i)	       /* convert EAX+2*EAX to 3*EAX */
		    b = -1, s++;
		if (b==-1 && s==1 && !(hb == i && ht == EAH_NOTBASE))
		    b = i, i = -1;     /* make single reg base, unless hint */
		if (((s==2 && i!=R_ESP && !(input->eaflags & EAF_TIMESTWO)) ||
		     s==3 || s==5 || s==9) && b==-1)
		    b = i, s--;       /* convert 3*EAX to EAX+2*EAX */
		if (i==-1 && b!=R_ESP && (input->eaflags & EAF_TIMESTWO))
		    i = b, b = -1, s = 1;
			/* convert [NOSPLIT EAX] to sib format with 0x0 displacement */
		if (s==1 && i==R_ESP)  /* swap ESP into base if scale is 1 */
		    i = b, b = R_ESP;
		if (i==R_ESP || (s!=1 && s!=2 && s!=4 && s!=8 && i!=-1))
		    return NULL;      /* wrong, for various reasons */

		if (i==-1 && b!=R_ESP) {/* no SIB needed */
		    int mod, rm;
		    switch(b) {
		      case R_EAX: rm = 0; break;
		      case R_ECX: rm = 1; break;
		      case R_EDX: rm = 2; break;
		      case R_EBX: rm = 3; break;
		      case R_EBP: rm = 5; break;
		      case R_ESI: rm = 6; break;
		      case R_EDI: rm = 7; break;
		      case -1: rm = 5; break;
		      default:	       /* should never happen */
			return NULL;
		    }
		    if (b==-1 || (b!=R_EBP && o==0 &&
				  seg==NO_SEG && !forw_ref &&
				  !(input->eaflags &
				    (EAF_BYTEOFFS|EAF_WORDOFFS))))
		    	mod = 0;
		    else if (input->eaflags & EAF_BYTEOFFS ||
			     (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
			      !(input->eaflags & EAF_WORDOFFS))) {
		    	mod = 1;
		    } 
		    else
		    	mod = 2;

		    output->sib_present = FALSE;
		    output->bytes = (b==-1 || mod==2 ? 4 : mod);
		    output->modrm = (mod<<6) | (rfield<<3) | rm;
		} 
		else {	       /* we need a SIB */
		    int mod, scale, index, base;

		    switch (b) {
		      case R_EAX: base = 0; break;
		      case R_ECX: base = 1; break;
		      case R_EDX: base = 2; break;
		      case R_EBX: base = 3; break;
		      case R_ESP: base = 4; break;
		      case R_EBP: case -1: base = 5; break;
		      case R_ESI: base = 6; break;
		      case R_EDI: base = 7; break;
		      default:	       /* then what the smeg is it? */
			return NULL;  /* panic */
		    }

		    switch (i) {
		      case R_EAX: index = 0; break;
		      case R_ECX: index = 1; break;
		      case R_EDX: index = 2; break;
		      case R_EBX: index = 3; break;
		      case -1: index = 4; break;
		      case R_EBP: index = 5; break;
		      case R_ESI: index = 6; break;
		      case R_EDI: index = 7; break;
		      default:	       /* then what the smeg is it? */
			return NULL;  /* panic */
		    }

		    if (i==-1) s = 1;
		    switch (s) {
		      case 1: scale = 0; break;
		      case 2: scale = 1; break;
		      case 4: scale = 2; break;
		      case 8: scale = 3; break;
		      default:	       /* then what the smeg is it? */
			return NULL;  /* panic */
		    }

		    if (b==-1 || (b!=R_EBP && o==0 &&
				  seg==NO_SEG && !forw_ref &&
				  !(input->eaflags &
				    (EAF_BYTEOFFS|EAF_WORDOFFS))))
		    	mod = 0;
		    else if (input->eaflags & EAF_BYTEOFFS ||
			     (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
			      !(input->eaflags & EAF_WORDOFFS)))
		    	mod = 1;
		    else
		    	mod = 2;

		    output->sib_present = TRUE;
		    output->bytes = (b==-1 || mod==2 ? 4 : mod);
		    output->modrm = (mod<<6) | (rfield<<3) | 4;
		    output->sib = (scale<<6) | (index<<3) | base;
		}
	    } 
	    else {		       /* it's 16-bit */
		int mod, rm;

		/* check all registers are BX, BP, SI or DI */
		if ((b!=-1 && b!=R_BP && b!=R_BX && b!=R_SI && b!=R_DI) ||
		    (i!=-1 && i!=R_BP && i!=R_BX && i!=R_SI && i!=R_DI))
		    return NULL;

		/* ensure the user didn't specify DWORD */
		if (input->addr_size == 32)
		    return NULL;

		if (s!=1 && i!=-1) return NULL;/* no can do, in 16-bit EA */
		if (b==-1 && i!=-1) { int tmp = b; b = i; i = tmp; } /* swap */
		if ((b==R_SI || b==R_DI) && i!=-1)
		  { int tmp = b; b = i; i = tmp; }
		                      /* have BX/BP as base, SI/DI index */
		if (b==i) return NULL;/* shouldn't ever happen, in theory */
		if (i!=-1 && b!=-1 &&
		    (i==R_BP || i==R_BX || b==R_SI || b==R_DI))
		    return NULL;      /* invalid combinations */
		if (b==-1)	      /* pure offset: handled above */
		    return NULL;      /* so if it gets to here, panic! */

		rm = -1;
		if (i!=-1)
		    switch (i*256 + b) {
		      case R_SI*256+R_BX: rm=0; break;
		      case R_DI*256+R_BX: rm=1; break;
		      case R_SI*256+R_BP: rm=2; break;
		      case R_DI*256+R_BP: rm=3; break;
		    }
		else
		    switch (b) {
		      case R_SI: rm=4; break;
		      case R_DI: rm=5; break;
		      case R_BP: rm=6; break;
		      case R_BX: rm=7; break;
		    }
		if (rm==-1)	       /* can't happen, in theory */
		    return NULL;      /* so panic if it does */

		if (o==0 && seg==NO_SEG && !forw_ref && rm!=6 &&
		    !(input->eaflags & (EAF_BYTEOFFS|EAF_WORDOFFS)))
		    mod = 0;
		else if (input->eaflags & EAF_BYTEOFFS ||
			 (o>=-128 && o<=127 && seg==NO_SEG && !forw_ref &&
			  !(input->eaflags & EAF_WORDOFFS)))
		    mod = 1;
		else
		    mod = 2;

		output->sib_present = FALSE;  /* no SIB - it's 16-bit */
		output->bytes = mod;  /* bytes of offset needed */
		output->modrm = (mod<<6) | (rfield<<3) | rm;
	    }
	}
    }
    output->size = 1 + output->sib_present + output->bytes;
    return output;
}

static int chsize (operand *input, int addrbits) 
{
    if (!(MEMORY & ~input->type)) {
	int i=input->indexreg, b=input->basereg;

	if (input->scale==0) i = -1;

	if (i == -1 && b == -1) /* pure offset */
	    return (input->addr_size != 0 && input->addr_size != addrbits);

	if (i==R_EAX || i==R_EBX || i==R_ECX || i==R_EDX
	    || i==R_EBP || i==R_ESP || i==R_ESI || i==R_EDI
	    || b==R_EAX || b==R_EBX || b==R_ECX || b==R_EDX
	    || b==R_EBP || b==R_ESP || b==R_ESI || b==R_EDI)
	    return (addrbits==16);
	else
	    return (addrbits==32);
    } 
    else
    	return 0;
}

⌨️ 快捷键说明

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