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

📄 parse_~2.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		e->left= a1;		e->right= a2;	}	return e;}/* We want to know the sizes of the first two operands. */static optype_t optypes[2];static int op_idx;static expression_t *bas_get_operand(int *pn)/* get something like: [memory], offset[base+index*scale], or simpler. */{	expression_t *e, *offset, *base, *index;	token_t *t;	int c;	optype_t optype;	/* Prefixed by 'byte', 'word' or 'dword'? */	if ((t= get_token(*pn))->type == T_WORD && (		strcmp(t->name, "byte") == 0		|| strcmp(t->name, "word") == 0		|| strcmp(t->name, "dword") == 0)	) {		switch (t->name[0]) {		case 'b':	optype= BYTE; break;		case 'w':	optype= use16() ? WORD : OWORD; break;		case 'd':	optype= use32() ? WORD : OWORD; break;		}		if (op_idx < arraysize(optypes)) optypes[op_idx++]= optype;		(*pn)++;		/* It may even be "byte ptr"... */		if ((t= get_token(*pn))->type == T_WORD					&& strcmp(t->name, "ptr") == 0) {			(*pn)++;		}	}	/* Is it [memory]? */	if (get_token(*pn)->symbol == '['		&& ((t= get_token(*pn + 1))->type != T_WORD			|| !isregister(t->name))	) {		/* A memory dereference. */		(*pn)++;		if ((offset= bas_get_C_expression(pn)) == nil) return nil;		if (get_token(*pn)->symbol != ']') {			parse_err(1, t, "operand syntax error\n");			del_expr(offset);			return nil;		}		(*pn)++;		e= new_expr();		e->operator= '(';		e->middle= offset;		return e;	}	/* #something? *something? */	if ((c= get_token(*pn)->symbol) == '#' || c == '*') {		/* '#' and '*' are often used to introduce some constant. */		(*pn)++;	}	/* Offset? */	if (get_token(*pn)->symbol != '[') {		/* There is an offset. */		if ((offset= bas_get_C_expression(pn)) == nil) return nil;	} else {		/* No offset. */		offset= nil;	}	/* [base]? [base+? base-? */	c= 0;	if (get_token(*pn)->symbol == '['		&& (t= get_token(*pn + 1))->type == T_WORD		&& isregister(t->name)		&& ((c= get_token(*pn + 2)->symbol) == ']' || c=='+' || c=='-')	) {		/* A base register expression. */		base= new_expr();		base->operator= 'B';		base->name= copystr(t->name);		(*pn)+= c == ']' ? 3 : 2;	} else {		/* No base register expression. */		base= nil;	}	/* +offset]? -offset]? */	if (offset == nil		&& (c == '+' || c == '-')		&& (t= get_token(*pn + 1))->type == T_WORD		&& !isregister(t->name)	) {		(*pn)++;		if ((offset= bas_get_C_expression(pn)) == nil) return nil;		if (get_token(*pn)->symbol != ']') {			parse_err(1, t, "operand syntax error\n");			del_expr(offset);			del_expr(base);			return nil;		}		(*pn)++;		c= 0;	}	/* [index*scale]? +index*scale]? */	if (c == '+' || get_token(*pn)->symbol == '[') {		/* An index most likely. */		token_t *m= nil;		if (!(		/* This must be true: */			(t= get_token(*pn + 1))->type == T_WORD			&& isregister(t->name)			&& (get_token(*pn + 2)->symbol == ']' || (				get_token(*pn + 2)->symbol == '*'				&& (m= get_token(*pn + 3))->type == T_WORD				&& strchr("1248", m->name[0]) != nil				&& m->name[1] == 0				&& get_token(*pn + 4)->symbol == ']'			))		)) {			/* Alas it isn't */			parse_err(1, t, "operand syntax error\n");			del_expr(offset);			del_expr(base);			return nil;		}		/* Found an index. */		index= new_expr();		index->operator= m == nil ? '1' : m->name[0];		index->name= copystr(t->name);		(*pn)+= (m == nil ? 3 : 5);	} else {		/* No index. */		index= nil;	}	if (base == nil && index == nil) {		/* Return a lone offset as is. */		e= offset;		/* Lone registers tell operand size. */		if (offset->operator == 'W' && isregister(offset->name)) {			switch (isregister(offset->name)) {			case 1:	optype= BYTE; break;			case 2:	optype= use16() ? WORD : OWORD; break;			case 4:	optype= use32() ? WORD : OWORD; break;			}			if (op_idx < arraysize(optypes))				optypes[op_idx++]= optype;		}	} else {		e= new_expr();		e->operator= 'O';		e->left= offset;		e->middle= base;		e->right= index;	}	return e;}static expression_t *bas_get_oplist(int *pn)/* Get a comma (or colon for jmpf and callf) separated list of instruction * operands. */{	expression_t *e, *o1, *o2;	token_t *t;	if ((e= bas_get_operand(pn)) == nil) return nil;	if ((t= get_token(*pn))->symbol == ',' || t->symbol == ':') {		o1= e;		(*pn)++;		if ((o2= bas_get_oplist(pn)) == nil) {			del_expr(o1);			return nil;		}		e= new_expr();		e->operator= ',';		e->left= o1;		e->right= o2;	}	return e;}static asm86_t *bas_get_statement(void)/* Get a pseudo op or machine instruction with arguments. */{	token_t *t= get_token(0);	asm86_t *a;	mnemonic_t *m;	int n;	int prefix_seen;	assert(t->type == T_WORD);	if (strcmp(t->name, ".sect") == 0) {		/* .sect .text etc.  Accept only four segment names. */		skip_token(1);		t= get_token(0);		if (t->type != T_WORD || (			strcmp(t->name, ".text") != 0			&& strcmp(t->name, ".rom") != 0			&& strcmp(t->name, ".data") != 0			&& strcmp(t->name, ".bss") != 0			&& strcmp(t->name, ".end") != 0		)) {			parse_err(1, t, "weird section name to .sect\n");			return nil;		}	}	a= new_asm86();	/* Process instruction prefixes. */	for (prefix_seen= 0;; prefix_seen= 1) {		if (strcmp(t->name, "rep") == 0			|| strcmp(t->name, "repe") == 0			|| strcmp(t->name, "repne") == 0			|| strcmp(t->name, "repz") == 0			|| strcmp(t->name, "repnz") == 0		) {			if (a->rep != ONCE) {				parse_err(1, t,					"can't have more than one rep\n");			}			switch (t->name[3]) {			case 0:		a->rep= REP;	break;			case 'e':			case 'z':	a->rep= REPE;	break;			case 'n':	a->rep= REPNE;	break;			}		} else		if (strcmp(t->name, "seg") == 0					&& get_token(1)->type == T_WORD) {			if (a->seg != DEFSEG) {				parse_err(1, t,				"can't have more than one segment prefix\n");			}			switch (get_token(1)->name[0]) {			case 'c':	a->seg= CSEG;	break;			case 'd':	a->seg= DSEG;	break;			case 'e':	a->seg= ESEG;	break;			case 'f':	a->seg= FSEG;	break;			case 'g':	a->seg= GSEG;	break;			case 's':	a->seg= SSEG;	break;			}			skip_token(1);		} else		if (!prefix_seen) {			/* No prefix here, get out! */			break;		} else {			/* No more prefixes, next must be an instruction. */			if (t->type != T_WORD				|| (m= search_mnem(t->name)) == nil				|| m->optype == PSEUDO			) {				parse_err(1, t,		"machine instruction expected after instruction prefix\n");				del_asm86(a);				return nil;			}			break;		}		/* Skip the prefix and extra newlines. */		do {			skip_token(1);		} while ((t= get_token(0))->symbol == ';');	}	/* All the readahead being done upsets the line counter. */	a->line= t->line;	/* Read a machine instruction or pseudo op. */	if ((m= search_mnem(t->name)) == nil) {		parse_err(1, t, "unknown instruction\n");		del_asm86(a);		return nil;	}	a->opcode= m->opcode;	a->optype= m->optype;	if (a->opcode == CBW || a->opcode == CWD) {		a->optype= (strcmp(t->name, "cbw") == 0		    || strcmp(t->name, "cwd") == 0) == use16() ? WORD : OWORD;	}	for (op_idx= 0; op_idx < arraysize(optypes); op_idx++)		optypes[op_idx]= m->optype;	op_idx= 0;	n= 1;	if (get_token(1)->symbol != ';'				&& (a->args= bas_get_oplist(&n)) == nil) {		del_asm86(a);		return nil;	}	if (m->optype == WORD) {		/* Does one of the operands overide the optype? */		for (op_idx= 0; op_idx < arraysize(optypes); op_idx++) {			if (optypes[op_idx] != m->optype)				a->optype= optypes[op_idx];		}	}	if (get_token(n)->symbol != ';') {		parse_err(1, t, "garbage at end of instruction\n");		del_asm86(a);		return nil;	}	switch (a->opcode) {	case DOT_ALIGN:		/* Restrict .align to have a single numeric argument, some		 * assemblers think of the argument as a power of two, so		 * we need to be able to change the value.		 */		if (strcmp(t->name, ".even") == 0 && a->args == nil) {			/* .even becomes .align 2. */			expression_t *e;			a->args= e= new_expr();			e->operator= 'W';			e->name= copystr("2");			e->len= 2;		}		if (a->args == nil || a->args->operator != 'W'					|| !isanumber(a->args->name)) {			parse_err(1, t,			  ".align is restricted to one numeric argument\n");			del_asm86(a);			return nil;		}		break;	case MOVSX:	case MOVZX:		/* Types of both operands tell the instruction type. */		a->optype= optypes[0];		if (optypes[1] == BYTE) {			a->opcode= a->opcode == MOVSX ? MOVSXB : MOVZXB;		}		break;	case SAL:	case SAR:	case SHL:	case SHR:	case RCL:	case RCR:	case ROL:	case ROR:		/* Only the first operand tells the operand size. */		a->optype= optypes[0];		break;	default:;	}	skip_token(n+1);	return a;}asm86_t *bas_get_instruction(void){	asm86_t *a= nil;	expression_t *e;	token_t *t;	while ((t= get_token(0))->symbol == ';')		skip_token(1);	if (t->type == T_EOF) return nil;	if (t->symbol == '#') {		/* Preprocessor line and file change. */		if ((t= get_token(1))->type != T_WORD || !isanumber(t->name)			|| get_token(2)->type != T_STRING		) {			parse_err(1, t, "file not preprocessed?\n");			zap();		} else {			set_file(get_token(2)->name,				strtol(get_token(1)->name, nil, 0) - 1);			/* GNU CPP adds extra cruft, simply zap the line. */			zap();		}		a= bas_get_instruction();	} else	if (t->type == T_WORD && get_token(1)->symbol == ':') {		/* A label definition. */		a= new_asm86();		a->line= t->line;		a->opcode= DOT_LABEL;		a->optype= PSEUDO;		a->args= e= new_expr();		e->operator= ':';		e->name= copystr(t->name);		skip_token(2);	} else	if (t->type == T_WORD && get_token(1)->symbol == '=') {		int n= 2;		if ((e= bas_get_C_expression(&n)) == nil) {			zap();			a= bas_get_instruction();		} else		if (get_token(n)->symbol != ';') {			parse_err(1, t, "garbage after assignment\n");			zap();			a= bas_get_instruction();		} else {			a= new_asm86();			a->line= t->line;			a->opcode= DOT_EQU;			a->optype= PSEUDO;			a->args= new_expr();			a->args->operator= '=';			a->args->name= copystr(t->name);			a->args->middle= e;			skip_token(n+1);		}	} else	if (t->type == T_WORD && get_token(1)->type == T_WORD				&& strcmp(get_token(1)->name, "lcomm") == 0) {		/* Local common block definition. */		int n= 2;		if ((e= bas_get_C_expression(&n)) == nil) {			zap();			a= bas_get_instruction();		} else		if (get_token(n)->symbol != ';') {			parse_err(1, t, "garbage after lcomm\n");			zap();			a= bas_get_instruction();		} else {			a= new_asm86();			a->line= t->line;			a->opcode= DOT_LCOMM;			a->optype= PSEUDO;			a->args= new_expr();			a->args->operator= ',';			a->args->right= e;			a->args->left= e= new_expr();			e->operator= 'W';			e->name= copystr(t->name);			e->len= strlen(e->name)+1;			skip_token(n+1);		}	} else	if (t->type == T_WORD) {		if ((a= bas_get_statement()) == nil) {			zap();			a= bas_get_instruction();		}	} else {		parse_err(1, t, "syntax error\n");		zap();		a= bas_get_instruction();	}	if (a->optype == OWORD) {		a->optype= WORD;		a->oaz|= OPZ;	}	return a;}

⌨️ 快捷键说明

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