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

📄 emit_gnu.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
}#define opcode2name(op)		(opcode2name_tab[op] + 0)static void gnu_put_string(const char *s, size_t n)/* Emit a string with weird characters quoted. */{	while (n > 0) {		int c= *s;		if (c < ' ' || c > 0177) {			gnu_printf("\\%03o", c);		} else		if (c == '"' || c == '\\') {			gnu_printf("\\%c", c & 0xFF);		} else {			gnu_putchar(c);		}		s++;		n--;	}}static void gnu_put_expression(asm86_t *a, expression_t *e, int deref)/* Send an expression, i.e. instruction operands, to the output file.  Deref * is true when the rewrite of "x" -> "#x" or "(x)" -> "x" may be made. */{	assert(e != nil);	switch (e->operator) {	case ',':		if (is_pseudo(a->opcode)) {			/* Pseudo's are normal. */			gnu_put_expression(a, e->left, deref);			gnu_printf(", ");			gnu_put_expression(a, e->right, deref);		} else {			/* He who invented GNU assembly has seen one VAX too			 * many, operands are given in the wrong order.  This			 * makes coding from an Intel databook a real delight.			 * A good thing this program allows us to write the			 * more normal ACK assembly.			 */			gnu_put_expression(a, e->right, deref);			gnu_printf(", ");			gnu_put_expression(a, e->left, deref);		}		break;	case 'O':		if (deref && a->optype == JUMP) gnu_putchar('*');		if (e->left != nil) gnu_put_expression(a, e->left, 0);		gnu_putchar('(');		if (e->middle != nil) gnu_put_expression(a, e->middle, 0);		if (e->right != nil) {			gnu_putchar(',');			gnu_put_expression(a, e->right, 0);		}		gnu_putchar(')');		break;	case '(':		if (!deref) gnu_putchar('(');		if (deref && a->optype == JUMP) gnu_putchar('*');		gnu_put_expression(a, e->middle, 0);		if (!deref) gnu_putchar(')');		break;	case 'B':		gnu_printf("%%%s", e->name);		break;	case '1':	case '2':	case '4':	case '8':		gnu_printf("%%%s,%c", e->name, e->operator);		break;	case '+':	case '-':	case '~':		if (e->middle != nil) {			if (deref && a->optype >= BYTE) gnu_putchar('$');			gnu_putchar(e->operator);			gnu_put_expression(a, e->middle, 0);			break;		}		/*FALL THROUGH*/	case '*':	case '/':	case '%':	case '&':	case '|':	case '^':	case S_LEFTSHIFT:	case S_RIGHTSHIFT:		if (deref && a->optype >= BYTE) gnu_putchar('$');		gnu_put_expression(a, e->left, 0);		if (e->operator == S_LEFTSHIFT) {			gnu_printf("<<");		} else		if (e->operator == S_RIGHTSHIFT) {			gnu_printf(">>");		} else {			gnu_putchar(e->operator);		}		gnu_put_expression(a, e->right, 0);		break;	case '[':		if (deref && a->optype >= BYTE) gnu_putchar('$');		gnu_putchar('(');		gnu_put_expression(a, e->middle, 0);		gnu_putchar(')');		break;	case 'W':		if (isregister(e->name)) {			if (a->optype == JUMP) gnu_putchar('*');			gnu_printf("%%%s", e->name);		} else {			if (deref && a->optype >= BYTE) gnu_putchar('$');			gnu_printf("%s", e->name);		}		break;	case 'S':		gnu_putchar('"');		gnu_put_string(e->name, e->len);		gnu_putchar('"');		break;	default:		fprintf(stderr,		"asmconv: internal error, unknown expression operator '%d'\n",			e->operator);		exit(1);	}}void gnu_emit_instruction(asm86_t *a)/* Output one instruction and its operands. */{	int same= 0;	char *p;	if (a == nil) {		/* Last call */		gnu_putchar('\n');		return;	}	if (use16()) {		fprintf(stderr,		"asmconv: the GNU assembler can't translate 8086 code\n");		exit(1);	}	/* Make sure the line number of the line to be emitted is ok. */	if ((a->file != efile && strcmp(a->file, efile) != 0)				|| a->line < eline || a->line > eline+10) {		gnu_putchar('\n');		gnu_printf("# %ld \"%s\"\n", a->line, a->file);		efile= a->file;		eline= a->line;	} else {		if (a->line == eline) {			gnu_printf("; ");			same= 1;		}		while (eline < a->line) {			gnu_putchar('\n');			eline++;		}	}	if (a->opcode == DOT_LABEL) {		assert(a->args->operator == ':');		gnu_printf("%s:", a->args->name);	} else	if (a->opcode == DOT_EQU) {		assert(a->args->operator == '=');		gnu_printf("\t%s = ", a->args->name);		gnu_put_expression(a, a->args->middle, 0);	} else	if (a->opcode == DOT_ALIGN) {		/* GNU .align thinks in powers of two. */		unsigned long n;		unsigned s;		assert(a->args->operator == 'W' && isanumber(a->args->name));		n= strtoul(a->args->name, nil, 0);		for (s= 0; s <= 4 && (1 << s) < n; s++) {}		gnu_printf(".align\t%u", s);	} else	if ((p= opcode2name(a->opcode)) != nil) {		if (!is_pseudo(a->opcode) && !same) gnu_putchar('\t');		switch (a->rep) {		case ONCE:	break;		case REP:	gnu_printf("rep; ");	break;		case REPE:	gnu_printf("repe; ");	break;		case REPNE:	gnu_printf("repne; ");	break;		default:	assert(0);		}		switch (a->seg) {		/* Kludge to avoid knowing where to put the "%es:" */		case DEFSEG:	break;		case CSEG:	gnu_printf(".byte 0x2e; ");	break;		case DSEG:	gnu_printf(".byte 0x3e; ");	break;		case ESEG:	gnu_printf(".byte 0x26; ");	break;		case FSEG:	gnu_printf(".byte 0x64; ");	break;		case GSEG:	gnu_printf(".byte 0x65; ");	break;		case SSEG:	gnu_printf(".byte 0x36; ");	break;		default:	assert(0);		}		/* Exceptions, exceptions... */		if (a->opcode == CBW) {			if (!(a->oaz & OPZ)) p= "cwde";			a->oaz&= ~OPZ;		}		if (a->opcode == CWD) {			if (!(a->oaz & OPZ)) p= "cdq";			a->oaz&= ~OPZ;		}		if (a->opcode == RET || a->opcode == RETF) {			/* Argument of RET needs a '$'. */			a->optype= WORD;		}		if (a->opcode == MUL && a->args != nil						&& a->args->operator == ',') {			/* Two operand MUL is an IMUL? */			p="imul%";		}		/* GAS doesn't understand the interesting combinations. */		if (a->oaz & ADZ) gnu_printf(".byte 0x67; ");		if (a->oaz & OPZ && strchr(p, '%') == nil)			gnu_printf(".byte 0x66; ");		/* Unsupported instructions that Minix code needs. */		if (a->opcode == JMPF && a->args != nil					&& a->args->operator == ',') {			/* JMPF seg:off. */			gnu_printf(".byte 0xEA; .long ");			gnu_put_expression(a, a->args->right, 0);			gnu_printf("; .short ");			gnu_put_expression(a, a->args->left, 0);			return;		}		if (a->opcode == JMPF && a->args != nil			&& a->args->operator == 'O'			&& a->args->left != nil			&& a->args->right == nil			&& a->args->middle != nil			&& a->args->middle->operator == 'B'			&& strcmp(a->args->middle->name, "esp") == 0		) {			/* JMPF offset(ESP). */			gnu_printf(".byte 0xFF,0x6C,0x24,");			gnu_put_expression(a, a->args->left, 0);			return;		}		if (a->opcode == MOV && a->args != nil			&& a->args->operator == ','			&& a->args->left != nil			&& a->args->left->operator == 'W'			&& (strcmp(a->args->left->name, "ds") == 0				|| strcmp(a->args->left->name, "es") == 0)			&& a->args->right->operator == 'O'			&& a->args->right->left != nil			&& a->args->right->right == nil			&& a->args->right->middle != nil			&& a->args->right->middle->operator == 'B'			&& strcmp(a->args->right->middle->name, "esp") == 0		) {			/* MOV DS, offset(ESP); MOV ES, offset(ESP) */			gnu_printf(".byte 0x8E,0x%02X,0x24,",				a->args->left->name[0] == 'd' ? 0x5C : 0x44);			gnu_put_expression(a, a->args->right->left, 0);			return;		}		if (a->opcode == MOV && a->args != nil			&& a->args->operator == ','			&& a->args->left != nil			&& a->args->left->operator == 'W'			&& (strcmp(a->args->left->name, "ds") == 0				|| strcmp(a->args->left->name, "es") == 0)			&& a->args->right->operator == '('			&& a->args->right->middle != nil		) {			/* MOV DS, (memory); MOV ES, (memory) */			gnu_printf(".byte 0x8E,0x%02X; .long ",				a->args->left->name[0] == 'd' ? 0x1D : 0x05);			gnu_put_expression(a, a->args->right->middle, 0);			return;		}		while (*p != 0) {			if (*p == '%') {				if (a->optype == BYTE) {					gnu_putchar('b');				} else				if (a->optype == WORD) {					gnu_putchar((a->oaz & OPZ) ? 'w' : 'l');				} else {					assert(0);				}			} else {				gnu_putchar(*p);			}			p++;		}		if (a->args != nil) {			static char *aregs[] = { "al", "ax", "eax" };			gnu_putchar('\t');			switch (a->opcode) {			case IN:				gnu_put_expression(a, a->args, 1);				gnu_printf(", %%%s", aregs[a->optype - BYTE]);				break;			case OUT:				gnu_printf("%%%s, ", aregs[a->optype - BYTE]);				gnu_put_expression(a, a->args, 1);				break;			default:				gnu_put_expression(a, a->args, 1);			}		}		if (a->opcode == DOT_USE16) set_use16();		if (a->opcode == DOT_USE32) set_use32();	} else {		fprintf(stderr,			"asmconv: internal error, unknown opcode '%d'\n",			a->opcode);		exit(1);	}}

⌨️ 快捷键说明

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