Chinaunix首页 | 论坛 | 博客
  • 博客访问: 361678
  • 博文数量: 64
  • 博客积分: 2975
  • 博客等级: 少校
  • 技术积分: 831
  • 用 户 组: 普通用户
  • 注册时间: 2007-01-14 10:59
文章存档

2014年(2)

2012年(7)

2010年(40)

2009年(5)

2008年(8)

2007年(2)

分类: LINUX

2010-03-30 11:54:29

1.伪指令概述

as支持非常多的伪指令,例如macro,if,rept,struct,include等等,这些伪指令对于汇编器处理能力的扩充非常重要,可以减少编程的工作量。从前面列出的伪指令来看,as支持宏汇编,条件汇编,以及循环、结构和文件包含等重要功能。


2.伪指令表初始化

as初始化的时候先建立伪指令表,便于迅速查找伪指令.

2.1 pobegin
main->read_begin->pobegin

static void
pobegin (void)
{
  po_hash = hash_new ();

  /* Do the target-specific pseudo ops.  */
  pop_table_name = "md";
  md_pop_insert ();

  /* Now object specific.  Skip any that were in the target table.  */
  pop_table_name = "obj";
  pop_override_ok = 1;
  obj_pop_insert ();

  /* Now portable ones.  Skip any that we've seen already.  */
  pop_table_name = "standard";
  pop_insert (potable);

#ifdef TARGET_USE_CFIPOP
  pop_table_name = "cfi";
  pop_override_ok = 1;
  cfi_pop_insert ();
#endif
}

po_hash显然用于存放所有伪指令的hash表,使用hash数据结构加速查找伪指令的速度.

2.2 md_pop_insert
main->read_begin->pobegin
{
  /* Do the target-specific pseudo ops.  */
  pop_table_name = "md";
  md_pop_insert ();
}

md_pop_insert初始化平台相关伪指令.

#ifndef md_pop_insert
#define md_pop_insert()        pop_insert(md_pseudo_table)
#endif

md_pseudo_table在gas/config/tc-i386.c中
const pseudo_typeS md_pseudo_table[] =
{
#if !defined(OBJ_AOUT) && !defined(USE_ALIGN_PTWO)
  {"align", s_align_bytes, 0},
#else
  {"align", s_align_ptwo, 0},
#endif
  {"arch", set_cpu_arch, 0},
#ifndef I386COFF
  {"bss", s_bss, 0},
#endif
  {"ffloat", float_cons, 'f'},
  {"dfloat", float_cons, 'd'},
  {"tfloat", float_cons, 'x'},
  {"value", cons, 2},
  {"slong", signed_cons, 4},
  {"noopt", s_ignore, 0},
  {"optim", s_ignore, 0},
  {"code16gcc", set_16bit_gcc_code_flag, CODE_16BIT},
  {"code16", set_code_flag, CODE_16BIT},
  {"code32", set_code_flag, CODE_32BIT},
  {"code64", set_code_flag, CODE_64BIT},
  {"intel_syntax", set_intel_syntax, 1},
  {"att_syntax", set_intel_syntax, 0},
#if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
  {"largecomm", handle_large_common, 0},
#else
  {"file", (void (*) (int)) dwarf2_directive_file, 0},
  {"loc", dwarf2_directive_loc, 0},
  {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
#endif
#ifdef TE_PE
  {"secrel32", pe_directive_secrel, 0},
#endif
  {0, 0, 0}
};

pseudo_typeS数据结构类型是

struct _pseudo_type
{
  /* assembler mnemonic, lower case, no '.' */
  const char *poc_name;
  /* Do the work */
  void (*poc_handler) (int);
  /* Value to pass to handler */
  int poc_val;
};

typedef struct _pseudo_type pseudo_typeS;

main->read_begin->pobegin->md_pop_insert->pop_insert
void
pop_insert (const pseudo_typeS *table)
{
  const char *errtxt;
  const pseudo_typeS *pop;
  for (pop = table; pop->poc_name; pop++)
    {
      errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);//插入hash表
      if (errtxt ////出错,
    && (!pop_override_ok //并且不允许重复定义
        || strcmp (errtxt, "exists")))//或者错误信息不是已存在该伪指令
    as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
          errtxt);//打印出现信息
    }
}

2.3 obj_pop_insert
main->read_begin->pobegin
{
  /* Now object specific.  Skip any that were in the target table.  */
  pop_table_name = "obj";
  pop_override_ok = 1;//<<<如果伪指令重复定义,不报错
  obj_pop_insert ();
}

obj_pop_insert初始化目标文件相关指令,目标文件一般是elf.

#ifndef obj_pop_insert
#define obj_pop_insert()    elf_pop_insert()
#endif

main->read_begin->pobegin->obj_pop_insert->elf_pop_insert

void
elf_pop_insert (void)
{
  pop_insert (elf_pseudo_table);
  if (ECOFF_DEBUGGING)
    pop_insert (ecoff_debug_pseudo_table);
}

下面是elf_pseudo_table的定义
static const pseudo_typeS elf_pseudo_table[] =
{
  {"comm", obj_elf_common, 0},
  {"common", obj_elf_common, 1},
  {"ident", obj_elf_ident, 0},
  {"lcomm", obj_elf_lcomm, 0},
  {"local", obj_elf_local, 0},
  {"previous", obj_elf_previous, 0},
  {"section", obj_elf_section, 0},
  {"section.s", obj_elf_section, 0},
  {"sect", obj_elf_section, 0},
  {"sect.s", obj_elf_section, 0},
  {"pushsection", obj_elf_section, 1},
  {"popsection", obj_elf_popsection, 0},
  {"size", obj_elf_size, 0},
  {"type", obj_elf_type, 0},
  {"version", obj_elf_version, 0},
  {"weak", obj_elf_weak, 0},

  /* These define symbol visibility.  */
  {"internal", obj_elf_visibility, STV_INTERNAL},
  {"hidden", obj_elf_visibility, STV_HIDDEN},
  {"protected", obj_elf_visibility, STV_PROTECTED},

  /* These are used for stabs-in-elf configurations.  */
  {"line", obj_elf_line, 0},

  /* This is a GNU extension to handle symbol versions.  */
  {"symver", obj_elf_symver, 0},

  /* A GNU extension to change subsection only.  */
  {"subsection", obj_elf_subsection, 0},

  /* These are GNU extensions to aid in garbage collecting C++ vtables.  */
  {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0},
  {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0},

  /* These are used for dwarf.  */
  {"2byte", cons, 2},
  {"4byte", cons, 4},
  {"8byte", cons, 8},
  /* These are used for dwarf2.  */
  { "file", (void (*) (int)) dwarf2_directive_file, 0 },
  { "loc",  dwarf2_directive_loc,  0 },
  { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },

  /* We need to trap the section changing calls to handle .previous.  */
  {"data", obj_elf_data, 0},
  {"offset", obj_elf_struct, 0},
  {"struct", obj_elf_struct, 0},
  {"text", obj_elf_text, 0},

  {"tls_common", obj_elf_tls_common, 0},

  /* End sentinel.  */
  {NULL, NULL, 0},
};

2.4初始化potable
main->read_begin->pobegin
{
  /* Now portable ones.  Skip any that we've seen already.  */
  pop_table_name = "standard";
  pop_insert (potable);
}

potable包括所有的可移植伪指令,这些伪指令可能和前面的指令重复,但是pop_override_ok已设置,不会有问题。
显然,potable包含了绝大部分伪指令。

static const pseudo_typeS potable[] = {
  {"abort", s_abort, 0},
  {"align", s_align_ptwo, 0},
  {"altmacro", s_altmacro, 1},
  {"ascii", stringer, 0},
  {"asciz", stringer, 1},
  {"balign", s_align_bytes, 0},
  {"balignw", s_align_bytes, -2},
  {"balignl", s_align_bytes, -4},
/* block  */
  {"byte", cons, 1},
  {"comm", s_comm, 0},
  {"common", s_mri_common, 0},
  {"common.s", s_mri_common, 1},
  {"data", s_data, 0},
  {"dc", cons, 2},
#ifdef TC_ADDRESS_BYTES
  {"dc.a", cons, 0},
#endif
  {"dc.b", cons, 1},
  {"dc.d", float_cons, 'd'},
  {"dc.l", cons, 4},
  {"dc.s", float_cons, 'f'},
  {"dc.w", cons, 2},
  {"dc.x", float_cons, 'x'},
  {"dcb", s_space, 2},
  {"dcb.b", s_space, 1},
  {"dcb.d", s_float_space, 'd'},
  {"dcb.l", s_space, 4},
  {"dcb.s", s_float_space, 'f'},
  {"dcb.w", s_space, 2},
  {"dcb.x", s_float_space, 'x'},
  {"ds", s_space, 2},
  {"ds.b", s_space, 1},
  {"ds.d", s_space, 8},
  {"ds.l", s_space, 4},
  {"ds.p", s_space, 12},
  {"ds.s", s_space, 4},
  {"ds.w", s_space, 2},
  {"ds.x", s_space, 12},
  {"debug", s_ignore, 0},
#ifdef S_SET_DESC
  {"desc", s_desc, 0},
#endif
/* dim  */
  {"double", float_cons, 'd'},
/* dsect  */
  {"eject", listing_eject, 0},    /* Formfeed listing.  */
  {"else", s_else, 0},
  {"elsec", s_else, 0},
  {"elseif", s_elseif, (int) O_ne},
  {"end", s_end, 0},
  {"endc", s_endif, 0},
  {"endfunc", s_func, 1},
  {"endif", s_endif, 0},
  {"endm", s_bad_end, 0},
  {"endr", s_bad_end, 1},
/* endef  */
  {"equ", s_set, 0},
  {"equiv", s_set, 1},
  {"eqv", s_set, -1},
  {"err", s_err, 0},
  {"error", s_errwarn, 1},
  {"exitm", s_mexit, 0},
/* extend  */
  {"extern", s_ignore, 0},    /* We treat all undef as ext.  */
  {"appfile", s_app_file, 1},
  {"appline", s_app_line, 1},
  {"fail", s_fail, 0},
  {"file", s_app_file, 0},
  {"fill", s_fill, 0},
  {"float", float_cons, 'f'},
  {"format", s_ignore, 0},
  {"func", s_func, 0},
  {"global", s_globl, 0},
  {"globl", s_globl, 0},
#ifdef OBJ_ELF
  {"gnu_attribute", s_gnu_attribute, 0},
#endif
  {"hword", cons, 2},
  {"if", s_if, (int) O_ne},
  {"ifb", s_ifb, 1},
  {"ifc", s_ifc, 0},
  {"ifdef", s_ifdef, 0},
  {"ifeq", s_if, (int) O_eq},
  {"ifeqs", s_ifeqs, 0},
  {"ifge", s_if, (int) O_ge},
  {"ifgt", s_if, (int) O_gt},
  {"ifle", s_if, (int) O_le},
  {"iflt", s_if, (int) O_lt},
  {"ifnb", s_ifb, 0},
  {"ifnc", s_ifc, 1},
  {"ifndef", s_ifdef, 1},
  {"ifne", s_if, (int) O_ne},
  {"ifnes", s_ifeqs, 1},
  {"ifnotdef", s_ifdef, 1},
  {"incbin", s_incbin, 0},
  {"include", s_include, 0},
  {"int", cons, 4},
  {"irp", s_irp, 0},
  {"irep", s_irp, 0},
  {"irpc", s_irp, 1},
  {"irepc", s_irp, 1},
  {"lcomm", s_lcomm, 0},
  {"lflags", listing_flags, 0},    /* Listing flags.  */
  {"linefile", s_app_line, 0},
  {"linkonce", s_linkonce, 0},
  {"list", listing_list, 1},    /* Turn listing on.  */
  {"llen", listing_psize, 1},
  {"long", cons, 4},
  {"lsym", s_lsym, 0},
  {"macro", s_macro, 0},
  {"mexit", s_mexit, 0},
  {"mri", s_mri, 0},
  {".mri", s_mri, 0},    /* Special case so .mri works in MRI mode.  */
  {"name", s_ignore, 0},
  {"noaltmacro", s_altmacro, 0},
  {"noformat", s_ignore, 0},
  {"nolist", listing_list, 0},    /* Turn listing off.  */
  {"nopage", listing_nopage, 0},
  {"octa", cons, 16},
  {"offset", s_struct, 0},
  {"org", s_org, 0},
  {"p2align", s_align_ptwo, 0},
  {"p2alignw", s_align_ptwo, -2},
  {"p2alignl", s_align_ptwo, -4},
  {"page", listing_eject, 0},
  {"plen", listing_psize, 0},
  {"print", s_print, 0},
  {"psize", listing_psize, 0},    /* Set paper size.  */
  {"purgem", s_purgem, 0},
  {"quad", cons, 8},
  {"reloc", s_reloc, 0},
  {"rep", s_rept, 0},
  {"rept", s_rept, 0},
  {"rva", s_rva, 4},
  {"sbttl", listing_title, 1},    /* Subtitle of listing.  */
/* scl  */
/* sect  */
  {"set", s_set, 0},
  {"short", cons, 2},
  {"single", float_cons, 'f'},
/* size  */
  {"space", s_space, 0},
  {"skip", s_space, 0},
  {"sleb128", s_leb128, 1},
  {"spc", s_ignore, 0},
  {"stabd", s_stab, 'd'},
  {"stabn", s_stab, 'n'},
  {"stabs", s_stab, 's'},
  {"string", stringer, 1},
  {"struct", s_struct, 0},
/* tag  */
  {"text", s_text, 0},

  /* This is for gcc to use.  It's only just been added (2/94), so gcc
     won't be able to use it for a while -- probably a year or more.
     But once this has been released, check with gcc maintainers
     before deleting it or even changing the spelling.  */
  {"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
  /* If we're folding case -- done for some targets, not necessarily
     all -- the above string in an input file will be converted to
     this one.  Match it either way...  */
  {"this_gcc_requires_the_gnu_assembler", s_ignore, 0},

  {"title", listing_title, 0},    /* Listing title.  */
  {"ttl", listing_title, 0},
/* type  */
  {"uleb128", s_leb128, 0},
/* use  */
/* val  */
  {"xcom", s_comm, 0},
  {"xdef", s_globl, 0},
  {"xref", s_ignore, 0},
  {"xstabs", s_xstab, 's'},
  {"warning", s_errwarn, 0},
  {"weakref", s_weakref, 0},
  {"word", cons, 2},
  {"zero", s_space, 0},
  {NULL, NULL, 0}            /* End sentinel.  */
};

阅读(2534) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~