gcc 源码分析:从IR-RTL 到汇编输出

gcc 源码分析--从gimple 到IR-RTL GCC编译器将GIMPLE中间表示转换为RTL中间表示的过程分为两部分:一部分是与目标架构无关的通用转换(如标签生成等),另一部分则依赖于目标架构描述文件。转换过程中会进行参数类型检查,并且一条GIMPLE语句可能对应多条RTL指令。该转换由pass_expand类实现,主要处理SSA形式转换、变量扩展、指令生成等工作,最终生成完整的RTL代码。 阅读详情

在完成了IR-RTL的优化与寄存器分配后

就来到汇编代码的输出:

实现如下:

class pass_final : public rtl_opt_pass
{
public:
  pass_final (gcc::context *ctxt)
    : rtl_opt_pass (pass_data_final, ctxt)
  {}

  /* opt_pass methods: */
  unsigned int execute (function *) final override
  {
    return rest_of_handle_final ();
  }

}; // class pass_final

} // anon namespace

rest_of_handle_final (void)
{
  const char *fnname = get_fnname_from_decl (current_function_decl);

  /* Turn debug markers into notes if the var-tracking pass has not
     been invoked.  */
  if (!flag_var_tracking && MAY_HAVE_DEBUG_MARKER_INSNS)
    delete_vta_debug_insns (false);

  assemble_start_function (current_function_decl, fnname);
  rtx_insn *first = get_insns ();
  int seen = 0;
  final_start_function_1 (&first, asm_out_file, &seen, optimize);
  final_1 (first, asm_out_file, seen, optimize);
  if (flag_ipa_ra
      && !lookup_attribute ("noipa", DECL_ATTRIBUTES (current_function_decl))
      /* Functions with naked attributes are supported only with basic asm
     statements in the body, thus for supported use cases the information
     on clobbered registers is not available.  */
      && !lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)))
    collect_fn_hard_reg_usage ();
  final_end_function ();

  /* The IA-64 ".handlerdata" directive must be issued before the ".endp"
     directive that closes the procedure descriptor.  Similarly, for x64 SEH.
     Otherwise it's not strictly necessary, but it doesn't hurt either.  */
  output_function_exception_table (crtl->has_bb_partition ? 1 : 0);

  assemble_end_function (current_function_decl, fnname);

  /* Free up reg info memory.  */
  free_reg_info ();

  if (! quiet_flag)
    fflush (asm_out_file);

  /* Note that for those inline functions where we don't initially
     know for certain that we will be generating an out-of-line copy,
     the first invocation of this routine (rest_of_compilation) will
     skip over this code by doing a `goto exit_rest_of_compilation;'.
     Later on, wrapup_global_declarations will (indirectly) call
     rest_of_compilation again for those inline functions that need
     to have out-of-line copies generated.  During that call, we
     *will* be routed past here.  */

  timevar_push (TV_SYMOUT);
  if (!DECL_IGNORED_P (current_function_decl))
    debug_hooks->function_decl (current_function_decl);
  timevar_pop (TV_SYMOUT);

  /* Release the blocks that are linked to DECL_INITIAL() to free the memory.  */
  DECL_INITIAL (current_function_decl) = error_mark_node;

  if (DECL_STATIC_CONSTRUCTOR (current_function_decl)
      && targetm.have_ctors_dtors)
    targetm.asm_out.constructor (XEXP (DECL_RTL (current_function_decl), 0),
                 decl_init_priority_lookup
                   (current_function_decl));
  if (DECL_STATIC_DESTRUCTOR (current_function_decl)
      && targetm.have_ctors_dtors)
    targetm.asm_out.destructor (XEXP (DECL_RTL (current_function_decl), 0),
                decl_fini_priority_lookup
                  (current_function_decl));
  return 0;
}

static void
final_1 (rtx_insn *first, FILE *file, int seen, int optimize_p)

{
  rtx_insn *insn, *next;

  /* Used for -dA dump.  */
  basic_block *start_to_bb = NULL;
  basic_block *end_to_bb = NULL;
  int bb_map_size = 0;
  int bb_seqn = 0;

  last_ignored_compare = 0;

  init_recog ();

  CC_STATUS_INIT;

  if (flag_debug_asm)
    {
      basic_block bb;

      bb_map_size = get_max_uid () + 1;
      start_to_bb = XCNEWVEC (basic_block, bb_map_size);
      end_to_bb = XCNEWVEC (basic_block, bb_map_size);

      /* There is no cfg for a thunk.  */
      if (!cfun->is_thunk)
    FOR_EACH_BB_REVERSE_FN (bb, cfun)
      {
        start_to_bb[INSN_UID (BB_HEAD (bb))] = bb;
        end_to_bb[INSN_UID (BB_END (bb))] = bb;
      }
    }

  /* Output the insns.  */
  for (insn = first; insn;)
    {
      if (HAVE_ATTR_length)
    {
      if ((unsigned) INSN_UID (insn) >= INSN_ADDRESSES_SIZE ())
        {
          /* This can be triggered by bugs elsewhere in the compiler if
         new insns are created after init_insn_lengths is called.  */
          gcc_assert (NOTE_P (insn));
          insn_current_address = -1;
        }
      else
        insn_current_address = INSN_ADDRESSES (INSN_UID (insn));
      /* final can be seen as an iteration of shorten_branches that
         does nothing (since a fixed point has already been reached).  */
      insn_last_address = insn_current_address;
    }

      dump_basic_block_info (file, insn, start_to_bb, end_to_bb,
                             bb_map_size, &bb_seqn);
      insn = final_scan_insn (insn, file, optimize_p, 0, &seen);
    }

  maybe_output_next_view (&seen);

  if (flag_debug_asm)
    {
      free (start_to_bb);
      free (end_to_bb);
    }

  /* Remove CFI notes, to avoid compare-debug failures.  */
  for (insn = first; insn; insn = next)
    {
      next = NEXT_INSN (insn);
      if (NOTE_P (insn)
      && (NOTE_KIND (insn) == NOTE_INSN_CFI
          || NOTE_KIND (insn) == NOTE_INSN_CFI_LABEL))
    delete_insn (insn);
    }
}

rtx_insn *
final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p,
         int nopeepholes, int *seen)

{
  static int *enclosing_seen;
  static int recursion_counter;

  gcc_assert (seen || recursion_counter);
  gcc_assert (!recursion_counter || !seen || seen == enclosing_seen);

  if (!recursion_counter++)
    enclosing_seen = seen;
  else if (!seen)
    seen = enclosing_seen;

  rtx_insn *ret = final_scan_insn_1 (insn, file, optimize_p, nopeepholes, seen);

  if (!--recursion_counter)
    enclosing_seen = NULL;

  return ret;
}

static rtx_insn *
final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
           int nopeepholes ATTRIBUTE_UNUSED, int *seen)

{
  rtx_insn *next;
  rtx_jump_table_data *table;

  insn_counter++;

  /* Ignore deleted insns.  These can occur when we split insns (due to a
     template of "#") while not optimizing.  */
  if (insn->deleted ())
    return NEXT_INSN (insn);

  switch (GET_CODE (insn))
    {
    case NOTE:
      switch (NOTE_KIND (insn))
    {
    case NOTE_INSN_DELETED:
    case NOTE_INSN_UPDATE_SJLJ_CONTEXT:
      break;

    case NOTE_INSN_SWITCH_TEXT_SECTIONS:
      maybe_output_next_view (seen);

      output_function_exception_table (0);

      if (targetm.asm_out.unwind_emit)
        targetm.asm_out.unwind_emit (asm_out_file, insn);

      in_cold_section_p = !in_cold_section_p;

      gcc_checking_assert (in_cold_section_p);
      if (in_cold_section_p)
        cold_function_name
          = clone_function_name (current_function_decl, "cold");

      if (dwarf2out_do_frame ())
        {
          dwarf2out_switch_text_section ();
          if (!dwarf2_debug_info_emitted_p (current_function_decl)
          && !DECL_IGNORED_P (current_function_decl))
        debug_hooks->switch_text_section ();
        }
      else if (!DECL_IGNORED_P (current_function_decl))
        debug_hooks->switch_text_section ();
      if (DECL_IGNORED_P (current_function_decl) && last_linenum
          && last_filename)
        debug_hooks->set_ignored_loc (last_linenum, last_columnnum,
                      last_filename);

      switch_to_section (current_function_section ());
      targetm.asm_out.function_switched_text_sections (asm_out_file,
                               current_function_decl,
                               in_cold_section_p);
      /* Emit a label for the split cold section.  Form label name by
         suffixing "cold" to the original function's name.  */
      if (in_cold_section_p)
        {
#ifdef ASM_DECLARE_COLD_FUNCTION_NAME
          ASM_DECLARE_COLD_FUNCTION_NAME (asm_out_file,
                          IDENTIFIER_POINTER
                              (cold_function_name),
                          current_function_decl);
#else
          ASM_OUTPUT_LABEL (asm_out_file,
                IDENTIFIER_POINTER (cold_function_name));
#endif
          if (dwarf2out_do_frame ()
              && cfun->fde->dw_fde_second_begin != NULL)
        ASM_OUTPUT_LABEL (asm_out_file, cfun->fde->dw_fde_second_begin);
        }
      break;

    case NOTE_INSN_BASIC_BLOCK:
      if (need_profile_function)
        {
          profile_function (asm_out_file);
          need_profile_function = false;
        }

      if (targetm.asm_out.unwind_emit)
        targetm.asm_out.unwind_emit (asm_out_file, insn);

      break;

    case NOTE_INSN_EH_REGION_BEG:
      ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHB",
                  NOTE_EH_HANDLER (insn));
      break;

    case NOTE_INSN_EH_REGION_END:
      ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LEHE",
                  NOTE_EH_HANDLER (insn));
      break;

    case NOTE_INSN_PROLOGUE_END:
      targetm.asm_out.function_end_prologue (file);
      profile_after_prologue (file);

      if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
        {
          *seen |= SEEN_EMITTED;
          force_source_line = true;
        }
      else
        *seen |= SEEN_NOTE;

      break;

    case NOTE_INSN_EPILOGUE_BEG:
          if (!DECL_IGNORED_P (current_function_decl))
            (*debug_hooks->begin_epilogue) (last_linenum, last_filename);
      targetm.asm_out.function_begin_epilogue (file);
      break;

    case NOTE_INSN_CFI:
      dwarf2out_emit_cfi (NOTE_CFI (insn));
      break;

    case NOTE_INSN_CFI_LABEL:
      ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LCFI",
                  NOTE_LABEL_NUMBER (insn));
      break;

    case NOTE_INSN_FUNCTION_BEG:
      if (need_profile_function)
        {
          profile_function (asm_out_file);
          need_profile_function = false;
        }

      app_disable ();
      if (!DECL_IGNORED_P (current_function_decl))
        debug_hooks->end_prologue (last_linenum, last_filename);

      if ((*seen & (SEEN_EMITTED | SEEN_NOTE)) == SEEN_NOTE)
        {
          *seen |= SEEN_EMITTED;
          force_source_line = true;
        }
      else
        *seen |= SEEN_NOTE;

      break;

    case NOTE_INSN_BLOCK_BEG:
      if (debug_info_level >= DINFO_LEVEL_NORMAL
          || dwarf_debuginfo_p ()
          || write_symbols == VMS_DEBUG)
        {
          int n = BLOCK_NUMBER (NOTE_BLOCK (insn));

          app_disable ();
          ++block_depth;
          high_block_linenum = last_linenum;

          /* Output debugging info about the symbol-block beginning.  */
          if (!DECL_IGNORED_P (current_function_decl))
        debug_hooks->begin_block (last_linenum, n, NOTE_BLOCK (insn));

          /* Mark this block as output.  */
          TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
          BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
        }
      break;

    case NOTE_INSN_BLOCK_END:
      maybe_output_next_view (seen);

      if (debug_info_level >= DINFO_LEVEL_NORMAL
          || dwarf_debuginfo_p ()
          || write_symbols == VMS_DEBUG)
        {
          int n = BLOCK_NUMBER (NOTE_BLOCK (insn));

          app_disable ();

          /* End of a symbol-block.  */
          --block_depth;
          gcc_assert (block_depth >= 0);

          if (!DECL_IGNORED_P (current_function_decl))
        debug_hooks->end_block (high_block_linenum, n);
          gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
              == in_cold_section_p);
        }
      break;

    case NOTE_INSN_DELETED_LABEL:
      /* Emit the label.  We may have deleted the CODE_LABEL because
         the label could be proved to be unreachable, though still
         referenced (in the form of having its address taken.  */
      ASM_OUTPUT_DEBUG_LABEL (file, "L", CODE_LABEL_NUMBER (insn));
      break;

    case NOTE_INSN_DELETED_DEBUG_LABEL:
      /* Similarly, but need to use different namespace for it.  */
      if (CODE_LABEL_NUMBER (insn) != -1)
        ASM_OUTPUT_DEBUG_LABEL (file, "LDL", CODE_LABEL_NUMBER (insn));
      break;

    case NOTE_INSN_VAR_LOCATION:
      if (!DECL_IGNORED_P (current_function_decl))
        {
          debug_hooks->var_location (insn);
          set_next_view_needed (seen);
        }
      break;

    case NOTE_INSN_BEGIN_STMT:
      gcc_checking_assert (cfun->debug_nonbind_markers);
      if (!DECL_IGNORED_P (current_function_decl)
          && notice_source_line (insn, NULL))
        {
        output_source_line:
          (*debug_hooks->source_line) (last_linenum, last_columnnum,
                       last_filename, last_discriminator,
                       true);
          clear_next_view_needed (seen);
        }
      break;

    case NOTE_INSN_INLINE_ENTRY:
      gcc_checking_assert (cfun->debug_nonbind_markers);
      if (!DECL_IGNORED_P (current_function_decl)
          && notice_source_line (insn, NULL))
        {
          (*debug_hooks->inline_entry) (LOCATION_BLOCK
                        (NOTE_MARKER_LOCATION (insn)));
          goto output_source_line;
        }
      break;

    default:
      gcc_unreachable ();
      break;
    }
      break;

    case BARRIER:
      break;

    case CODE_LABEL:
      /* The target port might emit labels in the output function for
     some insn, e.g. sh.cc output_branchy_insn.  */
      if (CODE_LABEL_NUMBER (insn) <= max_labelno)
    {
      align_flags alignment = LABEL_TO_ALIGNMENT (insn);
      if (alignment.levels[0].log && NEXT_INSN (insn))
        {
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
          /* Output both primary and secondary alignment.  */
          ASM_OUTPUT_MAX_SKIP_ALIGN (file, alignment.levels[0].log,
                     alignment.levels[0].maxskip);
          ASM_OUTPUT_MAX_SKIP_ALIGN (file, alignment.levels[1].log,
                     alignment.levels[1].maxskip);
#else
#ifdef ASM_OUTPUT_ALIGN_WITH_NOP
              ASM_OUTPUT_ALIGN_WITH_NOP (file, alignment.levels[0].log);
#else
          ASM_OUTPUT_ALIGN (file, alignment.levels[0].log);
#endif
#endif
        }
    }
      CC_STATUS_INIT;

      if (!DECL_IGNORED_P (current_function_decl) && LABEL_NAME (insn))
    debug_hooks->label (as_a <rtx_code_label *> (insn));

      app_disable ();

      /* If this label is followed by a jump-table, make sure we put
     the label in the read-only section.  Also possibly write the
     label and jump table together.  */
      table = jump_table_for_label (as_a <rtx_code_label *> (insn));
      if (table)
    {
#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
      /* In this case, the case vector is being moved by the
         target, so don't output the label at all.  Leave that
         to the back end macros.  */
#else
      if (! JUMP_TABLES_IN_TEXT_SECTION)
        {
          int log_align;

          switch_to_section (targetm.asm_out.function_rodata_section
                 (current_function_decl,
                  jumptable_relocatable ()));

#ifdef ADDR_VEC_ALIGN
          log_align = ADDR_VEC_ALIGN (table);
#else
          log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
#endif
          ASM_OUTPUT_ALIGN (file, log_align);
        }
      else
        switch_to_section (current_function_section ());

#ifdef ASM_OUTPUT_CASE_LABEL
      ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn), table);
#else
      targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
      break;
    }
      if (LABEL_ALT_ENTRY_P (insn))
    output_alternate_entry_point (file, insn);
      else
    targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
      break;

    default:
      {
    rtx body = PATTERN (insn);
    int insn_code_number;
    const char *templ;
    bool is_stmt, *is_stmt_p;

    if (MAY_HAVE_DEBUG_MARKER_INSNS && cfun->debug_nonbind_markers)
      {
        is_stmt = false;
        is_stmt_p = NULL;
      }
    else
      is_stmt_p = &is_stmt;

    /* Reset this early so it is correct for ASM statements.  */
    current_insn_predicate = NULL_RTX;

    /* An INSN, JUMP_INSN or CALL_INSN.
       First check for special kinds that recog doesn't recognize.  */

    if (GET_CODE (body) == USE /* These are just declarations.  */
        || GET_CODE (body) == CLOBBER)
      break;

    /* Detect insns that are really jump-tables
       and output them as such.  */

        if (JUMP_TABLE_DATA_P (insn))
      {
#if !(defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC))
        int vlen, idx;
#endif

        if (! JUMP_TABLES_IN_TEXT_SECTION)
          switch_to_section (targetm.asm_out.function_rodata_section
                 (current_function_decl,
                  jumptable_relocatable ()));
        else
          switch_to_section (current_function_section ());

        app_disable ();

#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
        if (GET_CODE (body) == ADDR_VEC)
          {
#ifdef ASM_OUTPUT_ADDR_VEC
        ASM_OUTPUT_ADDR_VEC (PREV_INSN (insn), body);
#else
        gcc_unreachable ();
#endif
          }
        else
          {
#ifdef ASM_OUTPUT_ADDR_DIFF_VEC
        ASM_OUTPUT_ADDR_DIFF_VEC (PREV_INSN (insn), body);
#else
        gcc_unreachable ();
#endif
          }
#else
        vlen = XVECLEN (body, GET_CODE (body) == ADDR_DIFF_VEC);
        for (idx = 0; idx < vlen; idx++)
          {
        if (GET_CODE (body) == ADDR_VEC)
          {
#ifdef ASM_OUTPUT_ADDR_VEC_ELT
            ASM_OUTPUT_ADDR_VEC_ELT
              (file, CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 0, idx), 0)));
#else
            gcc_unreachable ();
#endif
          }
        else
          {
#ifdef ASM_OUTPUT_ADDR_DIFF_ELT
            ASM_OUTPUT_ADDR_DIFF_ELT
              (file,
               body,
               CODE_LABEL_NUMBER (XEXP (XVECEXP (body, 1, idx), 0)),
               CODE_LABEL_NUMBER (XEXP (XEXP (body, 0), 0)));
#else
            gcc_unreachable ();
#endif
          }
          }
#ifdef ASM_OUTPUT_CASE_END
        ASM_OUTPUT_CASE_END (file,
                 CODE_LABEL_NUMBER (PREV_INSN (insn)),
                 insn);
#endif
#endif

        switch_to_section (current_function_section ());

        if (debug_variable_location_views
        && !DECL_IGNORED_P (current_function_decl))
          debug_hooks->var_location (insn);

        break;
      }
    /* Output this line note if it is the first or the last line
       note in a row.  */
    if (!DECL_IGNORED_P (current_function_decl)
        && notice_source_line (insn, is_stmt_p))
      {
        if (flag_verbose_asm)
          asm_show_source (last_filename, last_linenum);
        (*debug_hooks->source_line) (last_linenum, last_columnnum,
                     last_filename, last_discriminator,
                     is_stmt);
        clear_next_view_needed (seen);
      }
    else
      maybe_output_next_view (seen);

    gcc_checking_assert (!DEBUG_INSN_P (insn));

    if (GET_CODE (body) == PARALLEL
        && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
      body = XVECEXP (body, 0, 0);

    if (GET_CODE (body) == ASM_INPUT)
      {
        const char *string = XSTR (body, 0);

        /* There's no telling what that did to the condition codes.  */
        CC_STATUS_INIT;

        if (string[0])
          {
        expanded_location loc;

        app_enable ();
        loc = expand_location (ASM_INPUT_SOURCE_LOCATION (body));
        if (*loc.file && loc.line)
          fprintf (asm_out_file, "%s %i \"%s\" 1\n",
               ASM_COMMENT_START, loc.line, loc.file);
        fprintf (asm_out_file, "\t%s\n", string);
#if HAVE_AS_LINE_ZERO
        if (*loc.file && loc.line)
          fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
#endif
          }
        break;
      }

    /* Detect `asm' construct with operands.  */
    if (asm_noperands (body) >= 0)
      {
        unsigned int noperands = asm_noperands (body);
        rtx *ops = XALLOCAVEC (rtx, noperands);
        const char *string;
        location_t loc;
        expanded_location expanded;

        /* There's no telling what that did to the condition codes.  */
        CC_STATUS_INIT;

        /* Get out the operand values.  */
        string = decode_asm_operands (body, ops, NULL, NULL, NULL, &loc);
        /* Inhibit dying on what would otherwise be compiler bugs.  */
        insn_noperands = noperands;
        this_is_asm_operands = insn;
        expanded = expand_location (loc);

#ifdef FINAL_PRESCAN_INSN
        FINAL_PRESCAN_INSN (insn, ops, insn_noperands);
#endif

        /* Output the insn using them.  */
        if (string[0])
          {
        app_enable ();
        if (expanded.file && expanded.line)
          fprintf (asm_out_file, "%s %i \"%s\" 1\n",
               ASM_COMMENT_START, expanded.line, expanded.file);
            output_asm_insn (string, ops);
#if HAVE_AS_LINE_ZERO
        if (expanded.file && expanded.line)
          fprintf (asm_out_file, "%s 0 \"\" 2\n", ASM_COMMENT_START);
#endif
          }

        if (targetm.asm_out.final_postscan_insn)
          targetm.asm_out.final_postscan_insn (file, insn, ops,
                           insn_noperands);

        this_is_asm_operands = 0;
        break;
      }

    app_disable ();

    if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (body))
      {
        /* A delayed-branch sequence */
        int i;

        final_sequence = seq;

        /* The first insn in this SEQUENCE might be a JUMP_INSN that will
           force the restoration of a comparison that was previously
           thought unnecessary.  If that happens, cancel this sequence
           and cause that insn to be restored.  */

        next = final_scan_insn (seq->insn (0), file, 0, 1, seen);
        if (next != seq->insn (1))
          {
        final_sequence = 0;
        return next;
          }

        for (i = 1; i < seq->len (); i++)
          {
        rtx_insn *insn = seq->insn (i);
        rtx_insn *next = NEXT_INSN (insn);
        /* We loop in case any instruction in a delay slot gets
           split.  */
        do
          insn = final_scan_insn (insn, file, 0, 1, seen);
        while (insn != next);
          }
#ifdef DBR_OUTPUT_SEQEND
        DBR_OUTPUT_SEQEND (file);
#endif
        final_sequence = 0;

        /* If the insn requiring the delay slot was a CALL_INSN, the
           insns in the delay slot are actually executed before the
           called function.  Hence we don't preserve any CC-setting
           actions in these insns and the CC must be marked as being
           clobbered by the function.  */
        if (CALL_P (seq->insn (0)))
          {
        CC_STATUS_INIT;
          }
        break;
      }

    /* We have a real machine instruction as rtl.  */

    body = PATTERN (insn);

    /* Do machine-specific peephole optimizations if desired.  */

    if (HAVE_peephole && optimize_p && !flag_no_peephole && !nopeepholes)
      {
        rtx_insn *next = peephole (insn);
        /* When peepholing, if there were notes within the peephole,
           emit them before the peephole.  */
        if (next != 0 && next != NEXT_INSN (insn))
          {
        rtx_insn *note, *prev = PREV_INSN (insn);

        for (note = NEXT_INSN (insn); note != next;
             note = NEXT_INSN (note))
          final_scan_insn (note, file, optimize_p, nopeepholes, seen);

        /* Put the notes in the proper position for a later
           rescan.  For example, the SH target can do this
           when generating a far jump in a delayed branch
           sequence.  */
        note = NEXT_INSN (insn);
        SET_PREV_INSN (note) = prev;
        SET_NEXT_INSN (prev) = note;
        SET_NEXT_INSN (PREV_INSN (next)) = insn;
        SET_PREV_INSN (insn) = PREV_INSN (next);
        SET_NEXT_INSN (insn) = next;
        SET_PREV_INSN (next) = insn;
          }

        /* PEEPHOLE might have changed this.  */
        body = PATTERN (insn);
      }

    /* Try to recognize the instruction.
       If successful, verify that the operands satisfy the
       constraints for the instruction.  Crash if they don't,
       since `reload' should have changed them so that they do.  */

    insn_code_number = recog_memoized (insn);
    cleanup_subreg_operands (insn);

    /* Dump the insn in the assembly for debugging (-dAP).
       If the final dump is requested as slim RTL, dump slim
       RTL to the assembly file also.  */
    if (flag_dump_rtl_in_asm)
      {
        print_rtx_head = ASM_COMMENT_START;
        if (! (dump_flags & TDF_SLIM))
          print_rtl_single (asm_out_file, insn);
        else
          dump_insn_slim (asm_out_file, insn);
        print_rtx_head = "";
      }

    if (! constrain_operands_cached (insn, 1))
      fatal_insn_not_found (insn);

    /* Some target machines need to prescan each insn before
       it is output.  */

#ifdef FINAL_PRESCAN_INSN
    FINAL_PRESCAN_INSN (insn, recog_data.operand, recog_data.n_operands);
#endif

    if (targetm.have_conditional_execution ()
        && GET_CODE (PATTERN (insn)) == COND_EXEC)
      current_insn_predicate = COND_EXEC_TEST (PATTERN (insn));

    current_output_insn = debug_insn = insn;

    /* Find the proper template for this insn.  */
    templ = get_insn_template (insn_code_number, insn);

    /* If the C code returns 0, it means that it is a jump insn
       which follows a deleted test insn, and that test insn
       needs to be reinserted.  */
    if (templ == 0)
      {
        rtx_insn *prev;

        gcc_assert (prev_nonnote_insn (insn) == last_ignored_compare);

        /* We have already processed the notes between the setter and
           the user.  Make sure we don't process them again, this is
           particularly important if one of the notes is a block
           scope note or an EH note.  */
        for (prev = insn;
         prev != last_ignored_compare;
         prev = PREV_INSN (prev))
          {
        if (NOTE_P (prev))
          delete_insn (prev);    /* Use delete_note.  */
          }

        return prev;
      }

    /* If the template is the string "#", it means that this insn must
       be split.  */
    if (templ[0] == '#' && templ[1] == '\0')
      {
        rtx_insn *new_rtx = try_split (body, insn, 0);

        /* If we didn't split the insn, go away.  */
        if (new_rtx == insn && PATTERN (new_rtx) == body)
          fatal_insn ("could not split insn", insn);

        /* If we have a length attribute, this instruction should have
           been split in shorten_branches, to ensure that we would have
           valid length info for the splitees.  */
        gcc_assert (!HAVE_ATTR_length);

        return new_rtx;
      }

    /* ??? This will put the directives in the wrong place if
       get_insn_template outputs assembly directly.  However calling it
       before get_insn_template breaks if the insns is split.  */
    if (targetm.asm_out.unwind_emit_before_insn
        && targetm.asm_out.unwind_emit)
      targetm.asm_out.unwind_emit (asm_out_file, insn);

    rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn);
    if (call_insn != NULL)
      {
        rtx x = call_from_call_insn (call_insn);
        x = XEXP (x, 0);
        if (x && MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF)
          {
        tree t;
        x = XEXP (x, 0);
        t = SYMBOL_REF_DECL (x);
        if (t)
          assemble_external (t);
          }
      }

    /* Output assembler code from the template.  */
    output_asm_insn (templ, recog_data.operand);

    /* Some target machines need to postscan each insn after
       it is output.  */
    if (targetm.asm_out.final_postscan_insn)
      targetm.asm_out.final_postscan_insn (file, insn, recog_data.operand,
                           recog_data.n_operands);

    if (!targetm.asm_out.unwind_emit_before_insn
        && targetm.asm_out.unwind_emit)
      targetm.asm_out.unwind_emit (asm_out_file, insn);

    /* Let the debug info back-end know about this call.  We do this only
       after the instruction has been emitted because labels that may be
       created to reference the call instruction must appear after it.  */
    if ((debug_variable_location_views || call_insn != NULL)
        && !DECL_IGNORED_P (current_function_decl))
      debug_hooks->var_location (insn);

    current_output_insn = debug_insn = 0;
      }
    }
  return NEXT_INSN (insn);
}

const char *
get_insn_template (int code, rtx_insn *insn)

{
  switch (insn_data[code].output_format)
    {
    case INSN_OUTPUT_FORMAT_SINGLE:
      return insn_data[code].output.single;
    case INSN_OUTPUT_FORMAT_MULTI:
      return insn_data[code].output.multi[which_alternative];
    case INSN_OUTPUT_FORMAT_FUNCTION:
      gcc_assert (insn);
      return (*insn_data[code].output.function) (recog_data.operand, insn);

    default:
      gcc_unreachable ();
    }
}

gcc 源码分析:机器描述文件 GCC后端机器描述文件位于gcc/config目录中,各硬件平台有独立子目录,如xtensa平台包含xtensa.md(机器描述)、xtensa.h和xtensa.c三个核心文件。其中.h/.c文件定义目标机器的存储布局、调用规范等结构体targetm;.md文件则通过指令模板、属性定义等将机器特性引入编译器,指导IR-RTL到汇编的转换。关键转换过程分为两个阶段:GIMPLE到SPN的机器无关映射,以及SPN到IR-RTL的机器相关转换(通过匹配.md文件中命名的define_insn模板)。optabs 阅读详情

相关推荐

【源码解析】C/C++开源代码解析引擎

C/C++代码解析,代码重构或后处理

weixin_42932294的博客 3162

从GCC源码分析C语言编译原理——获取gcc源码

之前一直想自己发明一个新语言并配套搞个编译器来着,想了很久发现不太可行,付出与回报不成正比,也没法推广,现在没有一个新的语言的生存环境。所以就通过gcc的原理去对编译原理做加深性的学习吧。GCC(GNU Compiler Collection)是一个广泛使用的编译器集合,支持多种编程语言,如C、C++、Fortran等。

qq_52479948的博客 2487

startup_gd32f10x_md.s中汇编语法

下面把这个启动文件里常见的汇编符号,按“它像 C 里什么”来归类成一个速查表。这样你以后读启动文件就不会只看一大堆符号名了。相当于:uint32_t __Vectors[] = { ... };它不是“执行指令”,而是“存一份地址值”。while(1) { }或者一个死循环。全局函数或全局变量,允许别的文件引用。在数组中放一个 32 位常量值。全局符号定义 / 对外暴露。它是启动代码里最重要的函数。HardFault入口。不让异常时跑到随机地址。宏定义 / 常量定义。“定义一个段/区块”

tecoes的博客 166

GCC源码分析(五)——指令生成

原文链接:http://blog.youkuaiyun.com/sonicling/article/details/8246231 一、前言   又有好久没写了,的确很忙。前篇介绍了GCC的pass格局,它是GCC中间语言部分的核心架构,也是贯穿整个编译流程的核心。在完成优化处理之后,GCC必须做的最后一步就是生成最后的编译结果,通常情况下就是汇编文件(文本或者二进制并不重要)。

Windness的技术生活 3316

汇编 I/O 与中断:端口读写、中断向量表与 ISR

本文详解x86架构下I/O端口与中断机制,涵盖端口映射、IN/OUT指令、中断向量表(IVT)结构及中断处理流程。通过实模式下的键盘、定时器等硬件示例,揭示操作系统如何通过中断实现硬件管理,并演示自定义中断服务程序的安装与正确调用方式,强调保护现场、读取扫描码、避免重入等关键细节,为理解操作系统底层交互提供坚实基础。

软件工程师文艺 335

C 与汇编混合编程:符号链接、调用约定与参数传递

本文详解汇编与C语言混合编程的实现原理,涵盖PUBLIC与EXTERN指令的使用、32位调用约定(参数从右往左压栈、调用者清栈)、栈帧布局及寄存器保护规则。通过实例展示C调用汇编函数与汇编调用C库(如printf)的写法,并对比32位与64位(Windows x64)在参数传递、返回值和栈对齐上的差异。强调边界清晰的重要性,确保跨模块调用稳定可靠,适用于性能优化、硬件操作及学习底层机制场景。

软件工程师文艺 326

linux 中间代码反编译,[原创]反编译原理(2)-中间表示

中间语言通常情况下,反编译器和编译器一样,都分成前端、中端和后端三个部分,每一部分都有1-2种中间语言。如果使用3种中间语言,则前端中间语言定义为Target Dependent HIR,中端中间语言定义为Target Independent MIR,后端中间语言定义为Target Dependent LIR;如果使用4-6种中间语言,则前端中间语言定义为Target Dependent HIR和...

weixin_33925126的博客 577

LVGL v8.3 图片显示与解码缓存实战:PNG 上屏、C 数组与文件双方案

LVGL v8.3 图片两种存储方式、PNG/JPG 上屏解码器挂载、LV_IMG_CACHE_DEF_SIZE 缓存调优、手动预解码头像有效性判断,及"缓存被动画清空"真实踩坑。

汪同学的博客 408

Tcc源码解析:如何用2000行代码实现一个C编译器?

本文深入解析了Tiny C Compiler(Tcc)如何仅用约2000行核心代码实现一个完整的C编译器。通过剖析其极简设计、核心数据结构与独特的单趟编译流程,揭示了Tcc在舍弃复杂优化后,如何通过高度复用的代码路径和精巧的工程哲学,实现从源码到机器码的直接转换,为理解编译器本质和高效系统编程提供了绝佳范例。

book8的博客 253

关于LIO-SAM编译时出现错误 /usr/bin/ld: 找不到 -lBoost::timer

关于LIO-SAM编译时出现错误: 下载LIO-SAM代码 进入LIO-SAM文件夹,通过以下代码编译: mkdir build cd build cmake .. make 报错: /usr/bin/ld: 找不到 -lBoost::timer collect2: error: ld returned 1 exit status CMakeFiles/lio_sam_imuPreintegration.dir/build.make:759: recipe for target 'devel/lib/li

wwtx的博客 3648

Cursor 使用教程(2025年更新版)

官方Cursor详细使用教程在“扩展学习”

我是赛博AI Lewis 7082

硬核挑战:如果说精通 Linux 有段位,这份文档直接拉满宗师级

《Linux系统深度剖析》第一卷从计算机启动到用户空间初始化,深入解析了系统启动流程、工具链与ELF格式、Shell解释器等核心机制。文章详细拆解了从UEFI固件、GRUB2引导到内核初始化的完整启动链,揭示了PE/COFF格式、GPT分区表等底层细节。在工具链部分,系统剖析了GCC编译流程和ELF文件结构,重点讲解了动态链接中的PLT/GOT机制。最后通过Shell进程模型、管道重定向和信号处理,展现了用户空间与内核的交互原理。全文以寄存器状态、内存布局等硬件级视角,呈现Linux系统从电源接通到用户登录

qq_31815769的博客 1178

解决西门子Step 7 basic 找不到许可证问题

你在使用博图软件是否遇到过Step 7 basic 找不到许可证的问题呢!不言怕,今天我就来告诉你该如何处理吧!看步骤: 1.删除原授权的License: 打开Automation License Manager应用,然后我们可以发现仅有的License Key前面有一个时钟,说明它已经过期不可用,我们就要去寻求新的Key. 打开“我的电脑”,选择C盘,点击上方查看 点击选项–>查看 然...

让技术没有门槛 14万+

汇编调试实战:DEBUG、Turbo Debugger、GDB 与 IDA

本文系统讲解汇编调试技巧,涵盖 DEBUG.exe 基础使用(寄存器查看、单步执行、内存操作)、Turbo Debugger 图形化调试,以及 GDB(32位Linux)和逆向工具(IDA/Ghidra)的高级应用。重点解析寄存器管理、断点设置、栈平衡检查与常见错误排查,如死循环、内存越界、栈崩溃等,强调静态分析识别函数边界、动态分析验证逻辑流程。掌握这些方法可高效定位底层缺陷,提升汇编开发能力。

软件工程师文艺 231

西门子TM PosInput1模块SSI编码器配置与速度测量实战

本文详细介绍了西门子TM PosInput1模块配置SSI绝对值编码器的实战步骤,涵盖硬件组态、工艺对象配置、编程实现与速度测量优化。重点解析了高分辨率编码器的数值处理技巧和常见调试问题,帮助工程师快速实现高精度位置与速度检测,提升自动化项目效率。

emacs5lisp的博客 339

9篇3章3节:FAERS数据库公共仪表板搜索功能操作与解析

FAERS(FDA不良事件报告系统)公共仪表板是一个强大的工具,用于查询和分析药物及生物制品的不良事件数据。通过该仪表板,用户可以按药品或不良反应进行搜索,查看报告数量、事件类型及时间分布,从而辅助药物安全性分析和科研研究。本文重点介绍仪表板的搜索功能,包括按产品和按不良反应查询的操作步骤、筛选与多维数据分析方法,以及关键概念的解释,帮助用户科学、理性地使用FAERS数据,提升用药决策的准确性和安全性。

MD Code 1585

10个完整汇编实例:排序、字符串与递归算法

本文提供10个16位实模式下可运行的汇编程序,涵盖冒泡排序、字符串反转、进制转换、阶乘与斐波那契计算等经典算法,附逐行解析。重点讲解寄存器使用、循环控制、栈操作、除法清零、符号比较、字符处理等核心技巧,揭示如PUSH/POP CX保全计数器、DIV前清DX、ASCII转换、溢出处理等关键细节。通过实践掌握底层逻辑,提升汇编编程能力。

软件工程师文艺 227

EtherCAT主站SOEM -- 1 -- SOEM之ethercattype.h文件分析

“ethercattype.h” 文件用于支持 EtherCAT 网络通信,提供了各种类型定义和宏,以便开发者更轻松地开发 EtherCAT 相关应用程序。这些定义包括数据类型、命令类型、状态类型和错误类型,以支持 EtherCAT 通信。根据具体应用需求,还可以调整一些超时和帧长度设置。这些定义用于处理函数调用的结果,如 EC_NOFRAME(没有帧返回)、EC_ERROR(一般错误)、EC_TIMEOUT(请求超时)等。这些定义用于处理 EtherCAT 命令,例如 EC_CMD_APRD(自动递增读取

常驻客栈的博客--嵌入式EtherCAT 2714

ARM 汇编调试入门:MOV、LDR 和 STR

掌握,最重要的是看清数据移动的方向。

ccddvvv的博客 179

ORB-SLAM3编程实践指南

它基于特征点的立体视觉和视觉惯性里程计技术,能够在没有先验知识的情况下,从单目、双目或RGB-D摄像头的输入中实时构建稠密三维地图,并实现相机的定位。通过正确配置环境、准备数据集和运行ORB-SLAM3,您可以实现高效的视觉SLAM系统,并获取相机在三维空间中的位姿。其中,[path_to_vocabulary]是ORB-SLAM3的词汇文件路径,[path_to_settings]是相机参数配置文件路径,[path_to_sequence]是输入图像的路径。运行ORB-SLAM3。

ByteNinja的博客 551

在 SAP ECC 中定义 ledger 时遇到 “Define exactly one leading ledger“(消息号 FAGL_LEDGER_CUST012)的错误

摘要:SAP系统要求必须且只能定义一个主导分类账(Leading Ledger)。当出现错误消息FAGL_LEDGER_CUST012时,需通过事务码FINSC_LEDGER或SPRO路径检查分类账配置,确保仅有一个分类账被标记为"LeadingLedger",其余设为"Non-leadingLedger"。主导分类账是SAP默认用于标准报表的核心分类账,修改配置需谨慎以免影响已有数据。若问题未解决,建议检查未完成配置或查阅SAP Notes获取解决方案。

金牌架构师 802

汇编子程序设计:参数传递、局部变量与调用约定

汇编代码模块化核心在于子程序设计。通过PROC/ENDP定义函数,结合栈帧管理(PUSH BP/MOV BP, SP)实现局部变量隔离与递归支持。参数传递可选寄存器(高效)或栈(多参适用),配合调用约定(如C、Pascal)规范参数入栈顺序与栈清理责任。掌握这些模式,便能编写结构清晰、可复用的汇编代码,迈向工程化开发。

软件工程师文艺 226

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

四级 Linux 应用与开发工程师笔记:8086 汇编、存储器、接口芯片和操作系统计算题整理

计算机四级 Linux 应用与开发工程师备考笔记:这门考的不是 Linux 命令,而是操作系统原理和计算机组成与接口两门课。组成与接口部分重点整理 8086 寻址方式、常考汇编指令和读程序题、存储器位扩展和字扩展、流水线时空图,接口芯片和中断按做题方法整理;操作系统部分整理高响应比优先、Clock 置换、两级页表、生产者消费者等考点,配真题讲解。

qq_39121450的博客 231

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

C 语言:编译 → 汇编 → 链接 → 加载运行

C程序从源码到执行经历预处理、编译、汇编、链接四阶段,生成ELF可执行文件,由操作系统加载至内存并由CPU执行。关键点包括:交叉编译生成ARM指令;链接分静态与动态;入口为_start而非main;动态库需-fPIC保证位置无关性;嵌入式环境下可能跳过OS直接运行。

嵌入式开发,ARM Linux开发 411

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

汇编分支与循环:JMP/LOOP/条件跳转的结构化编程

本文详解如何用汇编的JMP与条件跳转实现if/else、for、while等高级控制流。通过循环计数、嵌套循环及复杂判断的典型模式,展示底层指令如何构建逻辑结构。掌握LOOP指令与跳转组合,即可在无高级语法环境下实现高效、精准的程序控制,体现汇编语言的简洁与性能优势。

软件工程师文艺 254

直接操作 VGA 显存:用汇编控制文本显示

本文详解VGA文本模式下直接操作显存的原理与实践:通过段寄存器B800h访问显存,每字符占2字节(ASCII+属性),利用偏移公式(n×80+m)×2定位输出。属性字节控制颜色与闪烁,如1Ch为蓝底亮红字。使用MOV ES:[DI], AX结合REP STOSW可高效清屏,配合INT 10h实现光标重置与滚动窗口。深入理解显存映射,是掌握图形底层逻辑的关键。

软件工程师文艺 199
上一篇: gcc 源码分析--从gimple 到IR-RTL
GoldKey
博客等级 码龄25年 82粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GoldKey

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值