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

📄 assemble.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
	    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 + -