?? asm.c
字號:
if (now_seg == SEG_TEXT)
symbolP->StorageClass = 6; /* Code label within a module */
else
symbolP->StorageClass = 3;
}
SetFlags(symbolP);
if (symbolP->Flags & IS_TEXT) {
symbolP->SectionNumber = SECTION_TEXT;
}
else if (symbolP->Flags & IS_DATA) {
symbolP->SectionNumber = SECTION_DATA;
}
}
}
static void SetFlags(symbolS *coffS)
{
if (now_seg == SEG_TEXT) {
coffS->Flags |= IS_TEXT;
coffS->Flags &= ~(IS_DATA | IS_BSS);
}
else if (now_seg == SEG_DATA) {
coffS->Flags |= IS_DATA;
coffS->Flags &= ~(IS_TEXT | IS_BSS);
}
}
/*
* symbol_find_or_make()
* If a symbol name does not exist, create it as undefined, and insert
* it into the symbol table. Return a pointer to it.
*/
static symbolS *symbol_find_or_make(char *name)
{
register symbolS *symbolP;
symbolP = symbol_table_lookup(name);
if (symbolP == NULL) {
symbolP = symbol_new(name, N_UNDF, 0, &zero_address_frag);
symbol_table_insert(symbolP);
}
return (symbolP);
}
/*
* frag_grow()
*
* Internal.
* Try to augment current frag by nchars chars.
* If there is no room, close of the current frag with a ".fill 0"
* and begin a new frag. Unless the new frag has nchars chars available
* do not return. Do not set up any fields of *now_frag.
*/
static void frag_grow(unsigned int nchars)
{
if (obstack_room(&frags) < nchars) {
unsigned int n, oldn;
long oldc;
frag_wane(frag_now);
frag_new(0);
oldn = (unsigned) -1;
oldc = frags.chunk_size;
frags.chunk_size = 2 * nchars;
while ((n = obstack_room(&frags)) < nchars && n < oldn) {
frag_wane(frag_now);
frag_new(0);
oldn = n;
}
frags.chunk_size = oldc;
}
else return;
if (obstack_room(&frags) < nchars) {
InternalError(1003);
}
}
/* frag_new()
* Call this to close off a completed frag, and start up a new (empty)
* frag, in the same subsegment as the old frag.
* [frchain_now remains the same but frag_now is updated.]
* Because this calculates the correct value of fr_fix by
* looking at the obstack 'frags', it needs to know how many
* characters at the end of the old frag belong to (the maximal)
* fr_var: the rest must belong to fr_fix.
* It doesn't actually set up the old frag's fr_var: you may have
* set fr_var == 1, but allocated 10 chars to the end of the frag:
* in this case you pass old_frags_var_max_size == 10.
* Make a new frag, initialising some components. Link new frag at end
* of frchain_now.
* input: old_frags_var_max_size Number of chars
* (already allocated on obstack frags) in variable_length part of frag.
*/
static void frag_new(int old_frags_var_max_size)
{
register fragS *former_last_fragP;
register frchainS *frchP;
long tmp;
frag_now->fr_fix = (char *) (obstack_next_free(&frags)) -
(frag_now->fr_literal) - old_frags_var_max_size;
/* Fix up old frag's fr_fix. */
obstack_finish(&frags);
/* This will align the obstack so the */
/* next struct we allocate on it will */
/* begin at a correct boundary. */
frchP = frchain_now;
know(frchP);
former_last_fragP = frchP->frch_last;
know(former_last_fragP);
know(former_last_fragP == frag_now);
obstack_blank(&frags, SIZEOF_STRUCT_FRAG);
/* We expect this will begin at a correct */
/* boundary for a struct. */
tmp = obstack_alignment_mask(&frags);
obstack_alignment_mask(&frags) = 0; /* Turn off alignment */
frag_now = (fragS *) obstack_finish(&frags);
obstack_alignment_mask(&frags) = tmp; /* Restore alignment */
/* Just in case we don't get zero'd bytes */
// memset(frag_now,0, SIZEOF_STRUCT_FRAG);
/* Generally, frag_now->points to an address rounded up to next
alignment. */
/* However, characters will add to obstack frags IMMEDIATELY after the
struct frag, */
/* even if they are not starting at an alignment address. */
former_last_fragP->fr_next = frag_now;
frchP->frch_last = frag_now;
frag_now->fr_next = NULL;
} /* frag_new() */
/* frag_more()
* Start a new frag unless we have n more chars of room in the current frag.
* Close off the old frag with a .fill 0.
* Return the address of the 1st char to write into. Advance
* frag_now_growth past the new chars.
*/
static char *frag_more(int nchars)
{
register char *retval;
frag_grow(nchars);
retval = obstack_next_free(&frags);
obstack_blank_fast(&frags, nchars);
return (retval);
} /* frag_more() */
/*
* frag_var()
* Start a new frag unless we have max_chars more chars of room in the current frag.
* Close off the old frag with a .fill 0.
*
* Set up a machine_dependent relaxable frag, then start a new frag.
* Return the address of the 1st char of the var part of the old frag
* to write into.
*/
static char *frag_var(
relax_stateT type,
int max_chars,
int var,
relax_substateT subtype,
symbolS *symbol,
long int offset,
char *opcode)
{
register char *retval;
frag_grow(max_chars);
retval = obstack_next_free(&frags);
obstack_blank_fast(&frags, max_chars);
frag_now->fr_var = var;
frag_now->fr_type = type;
frag_now->fr_subtype = subtype;
frag_now->fr_symbol = symbol;
frag_now->fr_offset = offset;
frag_now->fr_opcode = opcode;
frag_new(max_chars);
return (retval);
} /* frag_var() */
/*
* frag_wane() Reduce the variable end of a frag to a harmless state.
*/
static void frag_wane(fragS * fragP)
{
fragP->fr_type = rs_fill;
fragP->fr_offset = 0;
fragP->fr_var = 0;
}
/*
* frag_align()
* Make a frag for ".align foo,bar". Call is "frag_align (foo,bar);".
* Foo & bar are absolute integers.
* Call to close off the current frag with a ".align", then start a new
* (so far empty) frag, in the same subsegment as the last frag.
*/
static void frag_align(int alignment, int fill_character)
{
*(frag_var(rs_align, 1, 1, (relax_substateT) 0, (symbolS *) 0,
(long) alignment, (char *) 0)) = fill_character;
}
/*
* Summary of operand().
* in: InputPointer points to 1st char of operand, which may
* be a space.
* out: A expressionS. X_seg determines how to understand the rest of the
* expressionS.
* The operand may have been empty: in this case X_seg == SEG_NONE.
* InputPointer -> (next non-blank) char after operand.
*/
static segT operand(register expressionS *expressionP)
{
register char c;
register char *name;/* points to name of symbol */
register symbolS *symbolP; /* Points to symbol */
SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */
c = *InputPointer++; /* InputPointer -> past char in c. */
if (isdigit(c)) {
register valueT number; /* offset or (absolute) value */
register short int digit; /* value of next digit in current radix */
/* invented for humans only, hope */
/* optimising compiler flushes it! */
register short int radix; /* 8, 10 or 16 */
/* 0 means we saw start of a floating- */
/* point constant. */
register short int maxdig; /* Highest permitted digit value. */
register int too_many_digits; /* If we see >= this number of */
/* digits, assume it is a bignum. */
register char *digit_2; /* -> 2nd digit of number. */
int small; /* TRUE if fits in 32 bits. */
if (c == '0') { /* non-decimal radix */
if ((c = *InputPointer++) == 'x' || c == 'X') {
c = *InputPointer++; /* read past "0x" or "0X" */
maxdig = radix = 16;
too_many_digits = 9;
}
else {
/* If it says '0f' and the line ends or it DOESN'T look like
a floating point #, its a local label ref. DTRT */
if (c == 'f' && (!*InputPointer ||
(!index("+-.0123456789", *InputPointer)))) {
maxdig = radix = 10;
too_many_digits = 11;
c = '0';
InputPointer -= 2;
}
else { /* By elimination, assume octal radix. */
radix = 8;
maxdig = 10; /* Un*x sux. Compatibility. */
too_many_digits = 11;
}
}
/* c == char after "0" or "0x" or "0X" or "0e" etc. */
}
else {
maxdig = radix = 10;
too_many_digits = 11;
}
/*
* Most numbers fit into 32 bits, and we want this case to be fast.So we pretend it
will fit into 32 bits. If, after making up a 32 bit number, we realise that we
have scanned more digits than comfortably fit into 32 bits, we re-scan the digits
coding them into a bignum. For decimal and octal numbers we are conservative:
some numbers may be assumed bignums when in fact they do fit into 32 bits.Numbers
of any radix can have excess leading zeros: we strive to recognise this and cast
them back into 32 bits. The number we are looking for is expected to be positive,
but if it fits into 32 bits as an unsigned number, we let it be a 32-bit
number. The cavalier approach is for speed in ordinary cases.
*/
digit_2 = InputPointer;
for (number = 0; (digit = hex_value[c]) < maxdig; c = *InputPointer++) {
number = number * radix + digit;
}
/* C contains character after number. */
/* InputPointer -> char after C. */
small = InputPointer - digit_2 < too_many_digits;
if (!small) {
InternalError(1004);
}
/* Here with number, in correct radix. c is the next char. Note
that unlike Un*x, we allow "011f" "0x9f" to both mean the same
as the (conventional) "9f". This is simply easier than checking
for strict canonical form. Syntax sux! */
expressionP->X_add_number = number;
expressionP->X_seg = SEG_ABSOLUTE;
expressionP->X_subtract_symbol = NULL;
expressionP->X_add_symbol = NULL;
InputPointer--; /* Restore following character. */
SKIP_WHITESPACE(); /* -> 1st char after operand. */
know(*InputPointer != ' ');
return (expressionP->X_seg);
}
else if (c == '.' && !is_part_of_name(*InputPointer)) {
extern struct obstack frags;
/* '.' is pseudo symbol with value of current location in
current segment. . . */
symbolP = symbol_new("L0\001",
(unsigned char) (seg_N_TYPE[(int) now_seg]),
(valueT) (obstack_next_free(&frags) - frag_now->fr_literal),
frag_now);
expressionP->X_add_number = 0;
expressionP->X_add_symbol = symbolP;
expressionP->X_seg = now_seg;
}
else if (is_name_beginner(c)) { /* here if did not begin with a digit */
/* Identifier begins here. This is kludged for speed, so code is
repeated. */
name = --InputPointer;
c = get_symbol_end();
symbolP = symbol_table_lookup(name);
if (symbolP) {
/* If we have an absolute symbol, then we know it's value now. */
register segT seg;
seg = N_TYPE_seg[(int) symbolP->sy_type & N_TYPE];
if ((expressionP->X_seg = seg) == SEG_ABSOLUTE) {
expressionP->X_add_number = symbolP->SymbolValue;
}
else {
expressionP->X_add_number = 0;
expressionP->X_add_symbol = symbolP;
}
}
else {
expressionP->X_add_symbol
= symbolP
= symbol_new(name, N_UNDF, 0, &zero_address_frag);
expressionP->X_add_number = 0;
expressionP->X_seg = SEG_UNKNOWN;
symbol_table_insert(symbolP);
}
*InputPointer = c;
expressionP->X_subtract_symbol = NULL;
}
else if (c == '(') {/* didn't begin with digit & not a name */
(void) expression(expressionP);
/* Expression() will pass trailing whitespace */
if (*InputPointer++ != ')') {
InternalError(3061);
InputPointer--;
}
/* here with InputPointer -> char after "(...)" */
}
else if (c == '~' || c == '-') { /* unary operator: hope for
SEG_ABSOLUTE */
switch (operand(expressionP)) {
case SEG_ABSOLUTE:
/* InputPointer -> char after operand */
if (c == '-') {
expressionP->X_add_number = -expressionP->X_add_number;
/*
* Notice: '-' may overflow: no warning is given. This is compatible
* with other people's assemblers. Sigh.
*/
}
else {
expressionP->X_add_number = ~expressionP->X_add_number;
}
break;
case SEG_TEXT:
case SEG_DATA:
case SEG_BSS:
case SEG_PASS1:
case SEG_UNKNOWN:
if (c == '-') {
expressionP->X_subtract_symbol = expressionP->X_add_symbol;
expressionP->X_add_symbol = 0;
expressionP->X_seg = SEG_DIFFERENCE;
break;
}
default: /* unary on non-absolute is unsuported */
InternalError(3062);
break;
/* Expression undisturbed from operand(). */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -