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

📄 asm.c

📁 window下的c编译器。
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
	}
	else {
		/* can't imagine any other kind of operand */
		expressionP->X_seg = SEG_NONE;
		InputPointer--;
	}
/*
 * It is more 'efficient' to clean up the expressions when they are created.
 * Doing it here saves lines of code.
 */

	clean_up_expression(expressionP);
	SKIP_WHITESPACE();  /* -> 1st char after operand. */
	know(*InputPointer != ' ');
	return (expressionP->X_seg);
}                       /* operand */
/* Internal. Simplify a struct expression for use by AsmExpression()
 * In:  address of a expressionS.
 *  The X_seg field of the expressionS may only take certain values.
 *  Now, we permit SEG_PASS1 to make code smaller & faster.
 *  Elsewise we waste time special-case testing. Sigh. Ditto SEG_NONE.
 * Out: expressionS may have been modified:
 *  'foo-foo' symbol references cancelled to 0,
 *      which changes X_seg from SEG_DIFFERENCE to SEG_ABSOLUTE;
 *  Unused fields zeroed to help AsmExpression().
 */
static void clean_up_expression(register expressionS *expressionP)
{
	switch (expressionP->X_seg) {
	case SEG_NONE:
	case SEG_PASS1:
		expressionP->X_add_symbol = NULL;
		expressionP->X_subtract_symbol = NULL;
		expressionP->X_add_number = 0;
		break;
	case SEG_BIG:
	case SEG_ABSOLUTE:
		expressionP->X_subtract_symbol = NULL;
		expressionP->X_add_symbol = NULL;
		break;
	case SEG_TEXT:
	case SEG_DATA:
	case SEG_BSS:
	case SEG_UNKNOWN:
		expressionP->X_subtract_symbol = NULL;
		break;
	case SEG_DIFFERENCE:
		/* It does not hurt to 'cancel' NULL==NULL when comparing symbols for
		'eq'ness. It is faster to re-cancel them to NULL than to check for
		this special case. */
		if (expressionP->X_subtract_symbol == expressionP->X_add_symbol
				|| (expressionP->X_subtract_symbol
					&& expressionP->X_add_symbol
					&& expressionP->X_subtract_symbol->sy_frag == expressionP->X_add_symbol->sy_frag
					&& expressionP->X_subtract_symbol->SymbolValue == expressionP->X_add_symbol->SymbolValue)) {
			expressionP->X_subtract_symbol = NULL;
			expressionP->X_add_symbol = NULL;
			expressionP->X_seg = SEG_ABSOLUTE;
		}
		break;
	default:
		InternalError(1103);
		break;
	}
}
/*
 *          expr_part ()
 * Internal. Made a function because this code is used in 2 places.
 * Generate error or correct X_?????_symbol of expressionS.
 * symbol_1 += symbol_2 ... well ... sort of.
 */
static segT expr_part(symbolS **symbol_1_PP,symbolS * symbol_2_P)
{
	segT return_value;
	know((*symbol_1_PP) == NULL
		|| ((*symbol_1_PP)->sy_type & N_TYPE) == N_TEXT
		|| ((*symbol_1_PP)->sy_type & N_TYPE) == N_DATA
		|| ((*symbol_1_PP)->sy_type & N_TYPE) == N_BSS
		|| ((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF
		);
	know(symbol_2_P == NULL
		|| (symbol_2_P->sy_type & N_TYPE) == N_TEXT
		|| (symbol_2_P->sy_type & N_TYPE) == N_DATA
		|| (symbol_2_P->sy_type & N_TYPE) == N_BSS
		|| (symbol_2_P->sy_type & N_TYPE) == N_UNDF
		);
	if (*symbol_1_PP) {
		if (((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF) {
			if (symbol_2_P) {
				return_value = SEG_PASS1;
				*symbol_1_PP = NULL;
			}
			else {
				know(((*symbol_1_PP)->sy_type & N_TYPE) == N_UNDF);
				return_value = SEG_UNKNOWN;
			}
		}
		else {
			if (symbol_2_P) {
				if ((symbol_2_P->sy_type & N_TYPE) == N_UNDF) {
					*symbol_1_PP = NULL;
					return_value = SEG_PASS1;
				}
				else {
					/* {seg1} - {seg2} */
					InternalError(1063);
				}
			}
			else {
				return_value = N_TYPE_seg[(*symbol_1_PP)->sy_type & N_TYPE];
			}
		}
	}
	else {              /* (* symbol_1_PP) == NULL */
		if (symbol_2_P) {
			*symbol_1_PP = symbol_2_P;
			return_value = N_TYPE_seg[(symbol_2_P)->sy_type & N_TYPE];
		}
		else {
			*symbol_1_PP = NULL;
			return_value = SEG_ABSOLUTE;
		}
	}
	know(return_value == SEG_ABSOLUTE
		|| return_value == SEG_TEXT
		|| return_value == SEG_DATA
		|| return_value == SEG_BSS
		|| return_value == SEG_UNKNOWN
		|| return_value == SEG_PASS1
		);
	know((*symbol_1_PP) == NULL
	|| ((*symbol_1_PP)->sy_type & N_TYPE) == seg_N_TYPE[(int) return_value]);
	return (return_value);
}                       /* expr_part() */
/* Expression parser. */
/*
 * We allow an empty expression, and just assume (absolute,0) silently.
 * Unary operators and parenthetical expressions are treated as operands.
 * As usual, Q==quantity==operand, O==operator, X==expression mnemonics.
 * We used to do a aho/ullman shift-reduce parser, but the logic got so
 * warped that I flushed it and wrote a recursive-descent parser instead.
 * Now things are stable, would anybody like to write a fast parser?
 * Most expressions are either register (which does not even reach here)
 * or 1 symbol. Then "symbol+constant" and "symbol-symbol" are common.
 * So I guess it doesn't really matter how inefficient more complex expressions
 * are parsed.
 * After AsmExpression(RANK,resultP) InputPointer -> operator of rank <= RANK.
 * Also, we have consumed any leading or trailing spaces (operand does that)
 * and done all intervening operators.
 */
typedef enum {
	O_illegal,          /* (0)  what we get for illegal op */
	O_multiply,         /* (1)  * */
	O_divide,           /* (2)  / */
	O_modulus,          /* (3)  % */
	O_left_shift,       /* (4)  < */
	O_right_shift,      /* (5)  > */
	O_bit_inclusive_or, /* (6)  | */
	O_bit_or_not,       /* (7)  ! */
	O_bit_exclusive_or, /* (8)  ^ */
	O_bit_and,          /* (9)  & */
	O_add,              /* (10) + */
	O_subtract          /* (11) - */
}
operatorT;
#undef __
#define __ O_illegal
static const operatorT op_encoding[256] = { /* maps ASCII -> operators */
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, O_bit_or_not, __, __, __, O_modulus, O_bit_and, __,
	__, __, O_multiply, O_add, __, O_subtract, __, O_divide,
	__, __, __, __, __, __, __, __,
	__, __, __, __, O_left_shift, __, O_right_shift, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, __, __, O_bit_exclusive_or, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __,
	__, __, __, __, O_bit_inclusive_or, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,
	__, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __
};
/*
 *  Rank    Examples
 *  0   operand, (expression)
 *  1   + -
 *  2   & ^ ! |
 *  3   * / % < >
 */
static const operator_rankT
op_rank[] = {0, 3, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1};
static segT             /* Return resultP -> X_seg. */
AsmExpression(register operator_rankT rank,   /* Larger # is higher rank. */
	register expressionS *resultP)  /* Deliver result here. */
{
	expressionS right;
	register operatorT op_left;
	register char c_left;   /* 1st operator character. */
	register operatorT op_right;
	register char c_right;
	know(rank >= 0);
	(void) operand(resultP);
	know(*InputPointer != ' ');   /* Operand() gobbles spaces. */
	c_left = *InputPointer;   /* Potential operator character. */
	op_left = op_encoding[c_left];
	while (op_left != O_illegal && op_rank[(int) op_left] > rank) {
		InputPointer++;   /* -> after 1st character of operator. */
		/* Operators "<<" and ">>" have 2 characters. */
		if (*InputPointer == c_left && (c_left == '<' || c_left == '>')) {
			InputPointer++;
		}               /* -> after operator. */
		if (SEG_NONE == AsmExpression(op_rank[(int) op_left], &right)) {
			InternalError(1066);
		}
		know(*InputPointer != ' ');
		c_right = *InputPointer;
		op_right = op_encoding[c_right];
		if (*InputPointer == c_right && (c_right == '<' || c_right == '>')) {
			InputPointer++;
		}               /* -> after operator. */
		know((int) op_right == 0
			|| op_rank[(int) op_right] <= op_rank[(int) op_left]);
		/* InputPointer -> after right-hand quantity. */
		/* left-hand quantity in resultP */
		/* right-hand quantity in right. */
		/* operator in op_left. */
		if (resultP->X_seg == SEG_PASS1 || right.X_seg == SEG_PASS1) {
			resultP->X_seg = SEG_PASS1;
		}
		else {
			if (op_left == O_subtract) {
				/* Convert - into + by exchanging symbols and negating
				number. I know -infinity can't be negated in 2's
				complement: but then it can't be subtracted either. This
				trick does not cause any further inaccuracy. */
				register symbolS *symbolP;
				right.X_add_number = -right.X_add_number;
				symbolP = right.X_add_symbol;
				right.X_add_symbol = right.X_subtract_symbol;
				right.X_subtract_symbol = symbolP;
				if (symbolP) {
					right.X_seg = SEG_DIFFERENCE;
				}
				op_left = O_add;
			}
			if (op_left == O_add) {
				segT seg1;
				segT seg2;
				know(resultP->X_seg == SEG_DATA
					|| resultP->X_seg == SEG_TEXT
					|| resultP->X_seg == SEG_BSS
					|| resultP->X_seg == SEG_UNKNOWN
					|| resultP->X_seg == SEG_DIFFERENCE
					|| resultP->X_seg == SEG_ABSOLUTE
					|| resultP->X_seg == SEG_PASS1
					);
				know(right.X_seg == SEG_DATA
					|| right.X_seg == SEG_TEXT
					|| right.X_seg == SEG_BSS
					|| right.X_seg == SEG_UNKNOWN
					|| right.X_seg == SEG_DIFFERENCE
					|| right.X_seg == SEG_ABSOLUTE
					|| right.X_seg == SEG_PASS1
					);
				clean_up_expression(&right);
				clean_up_expression(resultP);
				seg1 = expr_part(&resultP->X_add_symbol, right.X_add_symbol);
				seg2 = expr_part(&resultP->X_subtract_symbol, right.X_subtract_symbol);
				if (seg1 == SEG_PASS1 || seg2 == SEG_PASS1) {
					need_pass_2 = TRUE;
					resultP->X_seg = SEG_PASS1;
				}
				else if (seg2 == SEG_ABSOLUTE)
					resultP->X_seg = seg1;
				else if (seg1 != SEG_UNKNOWN
						&& seg1 != SEG_ABSOLUTE
						&& seg2 != SEG_UNKNOWN
						&& seg1 != seg2) {
					know(seg2 != SEG_ABSOLUTE);
					know(resultP->X_subtract_symbol);
					know(seg1 == SEG_TEXT || seg1 == SEG_DATA || seg1 == SEG_BSS);
					know(seg2 == SEG_TEXT || seg2 == SEG_DATA || seg2 == SEG_BSS);
					know(resultP->X_add_symbol);
					know(resultP->X_subtract_symbol);
					InternalError(1067);
				}
				else
					resultP->X_seg = SEG_DIFFERENCE;
				resultP->X_add_number += right.X_add_number;
				clean_up_expression(resultP);
			}
			else {      /* Not +. */
				if (resultP->X_seg == SEG_UNKNOWN || right.X_seg == SEG_UNKNOWN) {
					resultP->X_seg = SEG_PASS1;
					need_pass_2 = TRUE;
				}
				else {
					resultP->X_subtract_symbol = NULL;
					resultP->X_add_symbol = NULL;
					/* Will be SEG_ABSOLUTE. */
					if (resultP->X_seg != SEG_ABSOLUTE || right.X_seg != SEG_ABSOLUTE) {
						InternalError(1068);
					}
					else {
						switch (op_left) {
						case O_bit_inclusive_or:
							resultP->X_add_number |= right.X_add_number;
							break;
						case O_modulus:
							if (right.X_add_number) {
								resultP->X_add_number %= right.X_add_number;
							}
							else {
								InternalError(1069);
							}
							break;
						case O_bit_and:
							resultP->X_add_number &= right.X_add_number;
							break;
						case O_multiply:
							resultP->X_add_number *= right.X_add_number;
							break;
						case O_divide:
							if (right.X_add_number) {
								resultP->X_add_number /= right.X_add_number;
							}
							else {
								InternalError(1069); /* division par zero */
							}
							break;
						case O_left_shift:
							resultP->X_add_number <<= right.X_add_number;
							break;
						case O_right_shift:
							resultP->X_add_number >>= right.X_add_number;
							break;
						case O_bit_exclusive_or:
							resultP->X_add_number ^= right.X_add_number;
							break;
						case O_bit_or_not:
							resultP->X_add_number |= ~right.X_add_number;
							break;
						default:
							InternalError(1104);
							break;
						}   /* switch(operator) */
					}
				}       /* If we have to force need_pass_2. */
			}           /* If operator was +. */
		}               /* If we didn't set need_pass_2. */
		op_left = op_right;
	}                   /* While next operator is >= this rank. */
	return (resultP->X_seg);
}
/* get_symbol_end()

⌨️ 快捷键说明

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