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

📄 assemble.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
	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");	    else {		long size = ins->oprs[0].offset << (c-0340);		if (size > 0)		    out (offset, segment, NULL,			 OUT_RESERVE+size, NO_SEG, NO_SEG);		offset += size;	    }	    break;	case 0370: case 0371: case 0372:	    break;		case 0373:	    *bytes = bits==16 ? 3 : 5;	    out (offset, segment, bytes,		 OUT_RAWDATA+1, NO_SEG, NO_SEG);	    offset += 1;	    break;	default:	               /* can't do it by 'case' statements */	    if (c>=0100 && c<=0277) {      /* it's an EA */		ea ea_data;		int rfield;		unsigned char *p;		long s;		if (c<=0177)	       /* pick rfield from operand b */		    rfield = regval (&ins->oprs[c&7]);		else 		       /* rfield is constant */		    rfield = c & 7;		if (!process_ea (&ins->oprs[(c>>3)&7], &ea_data, bits, rfield,				 ins->forw_ref))		{		    errfunc (ERR_NONFATAL, "invalid effective address");		}		p = bytes;		*p++ = ea_data.modrm;		if (ea_data.sib_present)		    *p++ = ea_data.sib;		s = p-bytes;		out (offset, segment, bytes, OUT_RAWDATA + s,		     NO_SEG, NO_SEG);		switch (ea_data.bytes) {		case 0:		    break;		case 1:		    if (ins->oprs[(c>>3)&7].segment != NO_SEG) {			data = ins->oprs[(c>>3)&7].offset;			out (offset, segment, &data, OUT_ADDRESS+1,			     ins->oprs[(c>>3)&7].segment,			     ins->oprs[(c>>3)&7].wrt);		    } else {			*bytes = ins->oprs[(c>>3)&7].offset;			out (offset, segment, bytes, OUT_RAWDATA+1,			     NO_SEG, NO_SEG);		    }		    s++;		    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 + -