📄 asm.c
字号:
#include "c.h"
#include "asm.h"
#include "i386.h"
#include "i386-opc.h"
#include "cv.h"
extern void * _stdcall GlobalAlloc(unsigned int,unsigned int);
extern void _stdcall GlobalFree(void *);
#define BUFFER_SIZE (32 * 1024)
typedef char operator_rankT;
extern int OptimizeFlag;
/* Prototypes */
static char * xmalloc (long n );
static void StringAppend (char * * charPP ,char * fromP ,unsigned long length );
static void subsegs_begin (void);
static void subseg_change (register segT seg ,register int subseg );
static void subseg_new (register segT seg ,register subsegT subseg );
static void symbol_begin (void);
static symbolS * symbol_new (char * name ,unsigned char type ,valueT value ,struct frag * frag );
static void colon (register char * sym_name );
static void symbol_table_insert (symbolS * symbolP );
static void SetFlags(symbolS *coffS);
static symbolS * symbol_find_or_make (char * name );
static void frag_grow (unsigned int nchars );
static void frag_new (int old_frags_var_max_size );
static char * frag_more (int nchars );
static char * frag_var (relax_stateT type ,int max_chars ,int var ,relax_substateT subtype ,symbolS * symbol ,long int offset ,char * opcode );
static void frag_wane (fragS * fragP );
static void frag_align (int alignment ,int fill_character );
static segT operand (register expressionS * expressionP );
static void clean_up_expression (register expressionS * expressionP );
static segT expr_part (symbolS * * symbol_1_PP ,symbolS * symbol_2_P );
static segT AsmExpression (register operator_rankT rank ,register expressionS * resultP );
static char get_symbol_end (void);
static char * input_file_give_next_buffer (char * where );
static void InitAsmInput (void);
static void SetObjFileName (char * filename );
static char * input_scrub_next_buffer (char * * bufp );
static void bump_line_counters (void);
static void as_where (void);
static void as_perror (char * gripe ,char * filename );
static void _obstack_begin (struct obstack * h ,int size ,int alignment ,void *(*chunkfun )(int),void (* freefun )(void *));
static void _obstack_newchunk (struct obstack * h ,int length );
static void read_begin (void);
static char * hash_insert (struct HASH_LIST * where ,char * name ,char * data );
static char * hash_find (struct HASH_LIST * w ,char * n );
static struct HASH_LIST * hash_new (void);
static char * hash_jam (struct HASH_LIST * where ,char * n ,char * data );
static void s_align (void);
static void s_byte(void);
static void s_short(void);
static void s_int(void);
static void s_comm (void);
static void s_data (void);
static void s_file (void);
static void s_globl (void);
static void s_lcomm (void);
static void s_line (void);
static void s_lsym (void);
static void s_space (void);
static void s_text (void);
static void s_section(void);
static void s_type (void);
static void s_size (void);
static void demand_empty_rest_of_line (void);
static void ignore_rest_of_line (void);
static void stab (int what );
static void pseudo_set (symbolS * symbolP );
static void cons (int nbytes );
static void stringer (int append_zero );
static int next_char_of_string (void);
static segT get_segmented_expression (register expressionS * expP );
static segT get_known_segmented_expression (expressionS * expP );
static long int get_absolute_expression (void);
static char get_absolute_expression_and_terminator (long int * val_pointer );
static char * demand_copy_C_string (int * len_pointer );
static char * demand_copy_string (int * lenP );
static int is_it_end_of_statement (void);
static void equals (char * sym_name );
static void InitializeAsmTables (void);
static int i386_operand (char *,char * );
static int md_estimate_size_before_relax (register fragS * fragP ,register int segment_type );
static void md_convert_frag (register fragS * fragP );
static void md_number_to_chars (char con [ ] ,long int value ,int nbytes );
static char * output_invalid (char c );
#ifndef ASM_LIB
static
#else
extern
#endif
reg_entry * parse_register (char * reg_string );
static void WriteCoffHeader (void);
static long WriteTextSection (long siz ,long nfixups );
static long WriteDataSection (long siz ,long nfixups ,int addr );
static long WriteBssSection (long siz );
static int ArrangeDataSection (int ordinal );
static int ArrangeOrdinalNumbers (char * name );
static int SortFun (const void * f1 ,const void * f2 );
static int WriteRelocations (int which);
static STRING * NewString (char * s ,int len );
static int AddStringToStringTable (char * str );
static long WriteStringTable (void);
static int SortSymbols (const void * f1 ,const void * f2 );
static int WriteLineNumbers (int PosCodeSection );
static int WriteOneSymbol (char * p );
static int WriteFunctionRecords (symbolS * coffS );
static int SymbolToChars (symbolS * coffS );
static int WriteDataSymbols (int count );
static int WriteSpecialSymbols (int result );
static int WriteAllCoffSymbols (int startCount );
static int WriteFileName (char * name );
static COFF_RELOC * AddCoffRelocation (symbolS * coffS ,int where ,int pcrel );
static void newFixup(fragS * frag ,int where ,short int size ,symbolS * add_symbol ,symbolS * sub_symbol ,long int offset ,int pcrel );
static void relax_segment (struct frag * segment_frag_root ,segT segment_type );
static relax_addressT relax_align (register relax_addressT address ,register long int alignment );
static long int fixup_segment (fixS * fixP ,int this_segment_type );
static int FixRelocations(register fixS * fixP);
#ifdef ASM_LIB
extern int is_dnrange (struct frag *f1,struct frag *f2);
#else
static int is_dnrange (struct frag * f1 ,struct frag * f2 );
#endif
int main (int argc ,char * * argv );
void WriteError(void);
void InternalError(int err);
static void MakeBssSymbol(symbolS *symbolP,int siz,int localflag);
#define HASHSIZE 1024
fixS * text_fix_root; /* Chains fixSs. */
fixS * data_fix_root; /* Chains fixSs. */
fixS ** seg_fix_rootP; /* -> one of above. */
/* --------------------------------------------------Sections stuff */
static int IsSpecialSection = 0;
static int NumberOfSpecialSections,NumberOfDebugSections;
NewSection *SectionList,*CurrentSpecialSection;
static void Asm386Instruction(char *line);
static struct obstack frags; /* All, and only, frags live here. */
static char * InputPointer; /* -> char we are parsing now. */
static STRING_TABLE *StringTable;
int need_pass_2; /* TRUE if we need a second pass. */
/* used by is_... macros. our ctype[] */
static char lex_type[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ABCDEFGHIJKLMNO */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* PQRSTUVWXYZ[\]^_ */
0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, /* _!"#$%&'()*+,-./ */
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 0123456789:;<=>? */
/* @ is part of name */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* @ABCDEFGHIJKLMNO */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, /* PQRSTUVWXYZ[\]^_ */
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* `abcdefghijklmno */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, /* pqrstuvwxyz{|}~. */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static char *buffer_limit; /* -> 1 + last char in buffer. */
static char *old_buffer = 0; /* JF a hack */
static char *old_input;
static char *old_limit;
static pseudo_typeS potable[] =
{
{"align", s_align},
{"byte", s_byte},
{"comm", s_comm},
{"data", s_data},
{"file", s_file},
{"globl", s_globl},
{"int", s_int},
{"lcomm", s_lcomm},
{"line", s_line},
{"long", s_int},
{"lsym", s_lsym},
{"short", s_short},
{"space", s_space},
{"text", s_text},
{"type", s_type},
{"size", s_size},
{"extern", s_globl},
{"bss", s_data},
{"section",s_section},
{"word", s_short},
{NULL} /* end sentinel */
};
/*
Interface to relax_segment.
There are 2 relax states for 386 jump insns: one for conditional & one
for unconditional jumps. This is because the these two types of jumps
add different sizes to frags when we're figuring out what sort of jump
to choose to reach a given label. */
/* types */
#define COND_JUMP 1 /* conditional jump */
#define UNCOND_JUMP 2 /* unconditional jump */
/* sizes */
#define BYTE 0
#define WORD 1
#define DWORD 2
#define UNKNOWN_SIZE 3
#define ENCODE_RELAX_STATE(type,size) ((type<<2) | (size))
#define SIZE_FROM_RELAX_STATE(s) \
( (((s) & 0x3) == BYTE ? 1 : (((s) & 0x3) == WORD ? 2 : 4)) )
static relax_typeS md_relax_table[] = {
/*
The fields are:
1) most positive reach of this state,
2) most negative reach of this state,
3) how many bytes this mode will add to the size of the current frag
4) which index into the table to try if we can't fit into this one.
*/
{1, 1, 0, 0},
{1, 1, 0, 0},
{1, 1, 0, 0},
{1, 1, 0, 0},
/* For now we don't use word displacement jumps: they may be
untrustworthy. */
{127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE(COND_JUMP, DWORD)},
/* word conditionals add 3 bytes to frag: 2 opcode prefix; 1 displacement
bytes */
{32767 + 2, -32768 + 2, 3, ENCODE_RELAX_STATE(COND_JUMP, DWORD)},
/* dword conditionals adds 4 bytes to frag: 1 opcode prefix; 3
displacement bytes */
{0, 0, 4, 0},
{1, 1, 0, 0},
{127 + 1, -128 + 1, 0, ENCODE_RELAX_STATE(UNCOND_JUMP, DWORD)},
/* word jmp adds 2 bytes to frag: 1 opcode prefix; 1 displacement bytes */
{32767 + 2, -32768 + 2, 2, ENCODE_RELAX_STATE(UNCOND_JUMP, DWORD)},
/* dword jmp adds 3 bytes to frag: 0 opcode prefix; 3 displacement bytes */
{0, 0, 3, 0},
{1, 1, 0, 0},
};
static frchainS *frchain_root, *frchain_now,
*data0_frchainP;
static fragS * frag_now; /* -> current frag we are building. */
/* This frag is incomplete. */
/* It is, however, included in frchain_now. */
/* Frag_now->fr_fix is bogus. Use: */
/* Virtual frag_now->fr_fix==obstack_next_free(&frags)-frag_now->fr_literal.*/
static fragS zero_address_frag = {
0, /* fr_address */
NULL, /* fr_next */
0, /* fr_fix */
0, /* fr_var */
0, /* fr_symbol */
0, /* fr_offset */
NULL, /* fr_opcode */
rs_fill, /* fr_type */
0, /* fr_subtype */
0 /* fr_literal [0] */
};
static fragS bss_address_frag = {
0, /* fr_address. Gets filled in to make up SymbolValue-s. */
NULL, /* fr_next */
0, /* fr_fix */
0, /* fr_var */
0, /* fr_symbol */
0, /* fr_offset */
NULL, /* fr_opcode */
rs_fill, /* fr_type */
0, /* fr_subtype */
0 /* fr_literal [0] */
};
static subsegT now_subseg;
/* What subseg we are accreting now? */
static segT now_seg;
/* Segment our instructions emit to. */
/* Only OK values are SEG_TEXT or SEG_DATA. */
static struct hash_control *sy_hash; /* symbol-name => struct symbol
pointer */
static unsigned int local_bss_counter;
static symbolS *symbol_rootP;
static symbolS *symbol_lastP;
static symbolS abs_symbol;
static struct obstack notes;
/* tables for lexical analysis */
static char opcode_chars[256];
#ifndef ASM_LIB
static
#endif
char register_chars[256];
static char operand_chars[256];
static char space_chars[256];
static char identifier_chars[256];
static char digit_chars[256];
#ifndef ASM_LIB
static
#endif
char RegisterNames[MAX_REG_NAMES * 6];
static char *SourceFileName = "";
char *OutputFileName;
/*
Errors
------
1000 Symbol is already defined
1001 Symbol %s already defined.
1002 Inserting symnol into symbol table failed
1003 Can't extend frag
1004 "integer overflow in constant"
1005 "No floating point constants supported"
1006 "Source line too long.
1007 error constructing pseudo-op table
1008 bad .type construct
1009 "Internal Error: Can't hash %s: %s", prev_name, hash_err
1010 Unknown pseudo-op:
1011 Spurious digit
1012 Synchronization problem at character ...
1013 Alignment too large
2014 Alignment negative
2015 Expected comma after symbol-name
2016 Bad expression
1017 Unknown expression: symbols %s and %s are in different frags
1018 invalid character %s in opcode"
1019 expecting prefix; got nothing"
1020 no such opcode prefix ('%s')", token_start)
1021 same prefix used twice; you don't really want this!
1022 too many opcode prefixes
1023 expecting opcode; got nothing
1024 no such 386 instruction: `%s'", token_start
1025 expecting string instruction after rep/repne
1026 invalid character %s before %s operand",
1027 unbalenced parenthesis in %s operand.",
1028 invalid character %s in %s operand",
1029 spurious operands; (%d operands/instruction max)
1030 expecting operand after ','; got nothing
1031 expecting operand before ','; got nothing
1032 operands given don't match any known 386 instruction
1033 no opcode suffix given; can't determine immediate size
1034 no opcode suffix given; can't determine immediate size
1035 no opcode suffix given and no register operands; can't size instruction
1036 %d prefixes given and 'w' opcode suffix gives too many prefixes",
1037 you can't 'pop cs' on the 386."
1038 %d prefixes given and %s segment override gives too many prefixes",
1039 "loop/jecx only takes byte displacement
1040 can't handle non absolute segment in long call/jmp"
1041 bad register name
1042 bad memory operand after segment override"
1043 only 1 or 2 immediate operands are allowed"
1044 missing or invalid immediate expression '%s'
1045 Unimplemented segment type %d in parse_operand"
1046 more than 1 memory reference in instruction"
1047 can't find base register name
1048 bad base register name
1049 expecting ',' or ')' after base register
1050 bad index register name
1051 can't find a scale factor after ','
1052 can't find a scale factor after ','
1053 expecting scale factor of 1, 2, 4, 8;
1054 expecting index register or scale factor after ','
2055 Ignoring junk '%s' after expression", InputPointer);
1056 missing or invalid displacement
1057 register size mismatch in (base,index,scale) expression
1058 base/index register must be 32 bit register"
1059 may not be used as an index register
1060 invalid char %s begining %s operand '%s'
3061 Missing ')' assumed"
3062 Unary operator %c ignored because bad operand follows", c);
1063 Expression too complex
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -