色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

main函數不一定就是程序入口

學益得智能硬件 ? 來源:學益得智能硬件 ? 2023-06-15 17:12 ? 次閱讀
我們都知道,main函數是C程序的入口,那這個入口能不能修改?
#include 


int main()
{
    return 0;
}
答案肯定是可以的,畢竟這個入口也是人為規定的。編譯分為4個步驟,預處理、編譯、匯編、鏈接。
gcc -E test.c -o test.i
gcc-Stest.i-otest.s
gcc -c test.s -o test.o
gcctest.o-otest
最后一步鏈接的時候,需要用到一個叫做鏈接腳本的東西,鏈接腳本就是類似于這樣的一個文件:
OUTPUT_ARCH( "riscv" )  /* 代碼采用的是RISC-V架構*/
ENTRY( _start )    /*代碼入口符號是_start,就是匯編啟動函數的符號*/
MEMORY
{
  /* 定義了一段起始地址為0x80000000,長度為128MB的內存區域,取名叫ram*/
  ram   (wxa!ri) : ORIGIN = 0x80000000, LENGTH = 128M
}
SECTIONS
{
  /* 所有輸入文件中的.text段、.text.*段都合在一起,組成輸出elf文件中的.text段;
  * 此外,定義了兩個符號_text_start和_text_end ,注意符號'.'代表的是當前地址;
  * 生成的.text段被放在了ram這個內存區域中。
  */
  .text : {
    PROVIDE(_text_start = .);
    *(.text .text.*)
    PROVIDE(_text_end = .);
  } >ram


  .rodata : {
    PROVIDE(_rodata_start = .);
    *(.rodata .rodata.*)
    PROVIDE(_rodata_end = .);
  } >ram


  .data : {
    . = ALIGN(4096);
    PROVIDE(_data_start = .);
    *(.sdata .sdata.*)
    *(.data .data.*)
    PROVIDE(_data_end = .);
  } >ram


  .bss :{
    PROVIDE(_bss_start = .);
    *(.sbss .sbss.*)
    *(.bss .bss.*)
    *(COMMON)
    PROVIDE(_bss_end = .);
  } >ram
  PROVIDE(_memory_start = ORIGIN(ram));
  PROVIDE(_memory_end = ORIGIN(ram) + LENGTH(ram));
  PROVIDE(_heap_start = _bss_end);
  PROVIDE(_heap_size = _memory_end - _heap_start);
}
它規定了程序的各個部分在內存中的位置,當然里面也包含了程序的入口:
ENTRY( _start )
只要修改了入口的名字,就能實現我們想要的功能。那么問題又來了,平時在編譯的時候,都是直接:
gcc hello.c
這個過程也沒看到什么鏈接腳本。
gcc其實是一系列工具的合集,如果你想看到詳細的步驟,編譯的時候加上-v選項就行。
gcc test.c -o test -v
最后一步鏈接的時候,都會默認使用編譯器自帶的鏈接腳本。Linux下,使用:
ld --verbose
可以拿到編譯器自帶的鏈接腳本。
/* Script for -z combreloc -z separate-code */
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
   Copying and distribution of this script, with or without modification,
   are permitted in any medium without royalty provided the copyright
   notice and this notice are preserved.  */
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
        "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_start)
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux
-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");SECTIONS
{
  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = 
SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;  .interp         : { *(.interp) }
  .note.gnu.build-id  : { *(.note.gnu.build-id) }
  .hash           : { *(.hash) }
  .gnu.hash       : { *(.gnu.hash) }
  .dynsym         : { *(.dynsym) }
  .dynstr         : { *(.dynstr) }
  .gnu.version    : { *(.gnu.version) }
  .gnu.version_d  : { *(.gnu.version_d) }
  .gnu.version_r  : { *(.gnu.version_r) }
  .rela.dyn       :
    {
      *(.rela.init)
      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
      *(.rela.fini)
      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
      *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
      *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
      *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
      *(.rela.ctors)
      *(.rela.dtors)
      *(.rela.got)
      *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
      *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
      *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
      *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
      *(.rela.ifunc)
    }
  .rela.plt       :
    {
      *(.rela.plt)
      PROVIDE_HIDDEN (__rela_iplt_start = .);
      *(.rela.iplt)
      PROVIDE_HIDDEN (__rela_iplt_end = .);
    }
  . = ALIGN(CONSTANT (MAXPAGESIZE));
  .init           :
  {
    KEEP (*(SORT_NONE(.init)))
  }
  .plt            : { *(.plt) *(.iplt) }
.plt.got        : { *(.plt.got) }
.plt.sec        : { *(.plt.sec) }
  .text           :
  {
    *(.text.unlikely .text.*_unlikely .text.unlikely.*)
    *(.text.exit .text.exit.*)
    *(.text.startup .text.startup.*)
    *(.text.hot .text.hot.*)
    *(SORT(.text.sorted.*))
    *(.text .stub .text.* .gnu.linkonce.t.*)
    /* .gnu.warning sections are handled specially by elf.em.  */
    *(.gnu.warning)
  }
  .fini           :
  {
    KEEP (*(SORT_NONE(.fini)))
  }
  PROVIDE (__etext = .);
  PROVIDE (_etext = .);
  PROVIDE (etext = .);
  . = ALIGN(CONSTANT (MAXPAGESIZE));
  /* Adjust the address for the rodata segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CO
NSTANT (MAXPAGESIZE) - 1)));  .rodata         : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
  .rodata1        : { *(.rodata1) }
  .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
  .gcc_except_table   : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) 
}  .gnu_extab   : ONLY_IF_RO { *(.gnu_extab*) }
  /* These sections are generated by the Sun/Oracle C++ compiler.  */
  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges*) }
  /* Adjust the address for the data segment.  We want to adjust up to
     the same address within the page on the next page up.  */
  . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
  /* Exception handling  */
  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
  .gnu_extab      : ONLY_IF_RW { *(.gnu_extab) }
  .gcc_except_table   : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) 
}  .exception_ranges   : ONLY_IF_RW { *(.exception_ranges*) }
  /* Thread Local Storage sections  */
  .tdata    :
   {
     PROVIDE_HIDDEN (__tdata_start = .);
     *(.tdata .tdata.* .gnu.linkonce.td.*)
   }
  .tbss      : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
  .preinit_array    :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  }
  .init_array    :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.
*)))    KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crte
nd?.o ) .ctors))    PROVIDE_HIDDEN (__init_array_end = .);
  }
  .fini_array    :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.
*)))    KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crte
nd?.o ) .dtors))    PROVIDE_HIDDEN (__fini_array_end = .);
  }
  .ctors          :
  {
    /* gcc uses crtbegin.o to find the start of
       the constructors, so we make sure it is
       first.  Because this is a wildcard, it
       doesn't matter if the user does not
       actually link against crtbegin.o; the
       linker won't look for a file to match a
       wildcard.  The wildcard also means that it
       doesn't matter which directory crtbegin.o
       is in.  */
    KEEP (*crtbegin.o(.ctors))
    KEEP (*crtbegin?.o(.ctors))
    /* We don't want to include the .ctor section from
       the crtend.o file until after the sorted ctors.
       The .ctor section from the crtend file contains the
       end of ctors marker and it must be last */
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
    KEEP (*(SORT(.ctors.*)))
    KEEP (*(.ctors))
  }
  .dtors          :
  {
    KEEP (*crtbegin.o(.dtors))
    KEEP (*crtbegin?.o(.dtors))
    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
    KEEP (*(SORT(.dtors.*)))
    KEEP (*(.dtors))
  }
  .jcr            : { KEEP (*(.jcr)) }
  .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.da
ta.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }  .dynamic        : { *(.dynamic) }
  .got            : { *(.got) *(.igot) }
  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
  .got.plt        : { *(.got.plt) *(.igot.plt) }
  .data           :
  {
    *(.data .data.* .gnu.linkonce.d.*)
    SORT(CONSTRUCTORS)
  }
  .data1          : { *(.data1) }
  _edata = .; PROVIDE (edata = .);
  . = .;
  __bss_start = .;
  .bss            :
  {
   *(.dynbss)
   *(.bss .bss.* .gnu.linkonce.b.*)
   *(COMMON)
   /* Align here to ensure that the .bss section occupies space up to
      _end.  Align after .bss to ensure correct alignment even if the
      .bss section disappears because there are no input sections.
      FIXME: Why do we need it? When there is no .bss section, we do not
      pad the .data section.  */
   . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  .lbss   :
  {
    *(.dynlbss)
    *(.lbss .lbss.* .gnu.linkonce.lb.*)
    *(LARGE_COMMON)
  }
  . = ALIGN(64 / 8);
  . = SEGMENT_START("ldata-segment", .);
  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)
) :  {
    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
  }
  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) 
:  {
    *(.ldata .ldata.* .gnu.linkonce.l.*)
    . = ALIGN(. != 0 ? 64 / 8 : 1);
  }
  . = ALIGN(64 / 8);
  _end = .; PROVIDE (end = .);
  . = DATA_SEGMENT_END (.);
  /* Stabs debugging sections.  */
  .stab          0 : { *(.stab) }
  .stabstr       0 : { *(.stabstr) }
  .stab.excl     0 : { *(.stab.excl) }
  .stab.exclstr  0 : { *(.stab.exclstr) }
  .stab.index    0 : { *(.stab.index) }
  .stab.indexstr 0 : { *(.stab.indexstr) }
  .comment       0 : { *(.comment) }
  .gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
  /* DWARF debug sections.
     Symbols in the DWARF debugging sections are relative to the beginning
     of the section so we begin them at 0.  */
  /* DWARF 1 */
  .debug          0 : { *(.debug) }
  .line           0 : { *(.line) }
  /* GNU DWARF 1 extensions */
  .debug_srcinfo  0 : { *(.debug_srcinfo) }
  .debug_sfnames  0 : { *(.debug_sfnames) }
  /* DWARF 1.1 and DWARF 2 */
  .debug_aranges  0 : { *(.debug_aranges) }
  .debug_pubnames 0 : { *(.debug_pubnames) }
  /* DWARF 2 */
  .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
  .debug_abbrev   0 : { *(.debug_abbrev) }
  .debug_line     0 : { *(.debug_line .debug_line.* .debug_line_end) }
  .debug_frame    0 : { *(.debug_frame) }
  .debug_str      0 : { *(.debug_str) }
  .debug_loc      0 : { *(.debug_loc) }
  .debug_macinfo  0 : { *(.debug_macinfo) }
  /* SGI/MIPS DWARF 2 extensions */
  .debug_weaknames 0 : { *(.debug_weaknames) }
  .debug_funcnames 0 : { *(.debug_funcnames) }
  .debug_typenames 0 : { *(.debug_typenames) }
  .debug_varnames  0 : { *(.debug_varnames) }
  /* DWARF 3 */
  .debug_pubtypes 0 : { *(.debug_pubtypes) }
  .debug_ranges   0 : { *(.debug_ranges) }
  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
  .debug_addr     0 : { *(.debug_addr) }
  .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
我們把它導入一個文件中,后綴就叫lds吧。
ld--verbose>xx.lds
為了滿足它的語法規則,還得刪除一些東西,保留這兩條杠之間的內容即可。看下鏈接腳本,找到ENTRY,就是程序的入口。
ENTRY(_start)
不過它并不是main函數,而是_start函數。因為在執行用戶的代碼之前,還有很多事情要做,這個后面在講。如果要修改程序的入口,只要把_start改掉就行,比如改成test,然后保存文件。
ENTRY(test)
寫個測試代碼,代碼中有main函數,也有test函數,test就是剛才我們說的入口,不過得指定退出方式,要不然程序運行的時候會出問題。
#include 
#include 


voidtest()
{
    printf("this is test ...
");
exit(0);
}


int main()
{
    printf("helloworld
");
    return 0;
}
編譯代碼,使用-T選項,指定鏈接腳本。
gcctest.c-otest-Txx.lds
運行程序,代碼執行的是test函數。
root@Turbo:test# ./test 
this is test ...
root@Turbo:test#
修改程序的入口還有一個更簡單的方法,gcc編譯的時候,直接使用-e選項,也能達到一樣的效果。
gcc test.c -o test -e test

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 程序
    +關注

    關注

    117

    文章

    3789

    瀏覽量

    81140
  • 函數
    +關注

    關注

    3

    文章

    4333

    瀏覽量

    62723
  • 編譯
    +關注

    關注

    0

    文章

    659

    瀏覽量

    32899

原文標題:main函數不一定就是程序入口

文章出處:【微信號:學益得智能硬件,微信公眾號:學益得智能硬件】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    main函數不一定就是程序入口

    我們都知道,main函數是C程序入口,那這個入口能不能修改?
    發表于 06-15 17:09 ?563次閱讀

    網友可能不一定很了解的時間單位

    時間單位有的網友可能不一定很了解,特別是搞FPGA的網友,提供。 無限可分,沒有最小。 s(秒)以下的時間單位(千進制): 1s (秒) =1000 ms (毫秒) 1ms (毫秒) =1000
    發表于 01-11 11:59

    gpio和中斷斷開發現喚醒后中斷不一定及時響應是為什么?

    斷開,發現喚醒后中斷不一定及時響應,即使響應了系統也死掉了,請問這種情況怎么解決呢?我在idle_profile的基礎上做的實驗。deepsleep模式的功耗有點兒高了。
    發表于 06-12 16:42

    為什么高速USB并不一定表示手機擁有高速性能

    為什么高速USB并不一定表示手機擁有高速性能 數碼多媒體向日用電器的發展改變了消費者接觸和享受多媒體娛樂節目的方式。現在消費者可以通過撲克牌大小的設備來
    發表于 01-04 11:21 ?642次閱讀
    為什么高速USB并<b class='flag-5'>不一定</b>表示手機擁有高速性能

    C語言程序main函數免費下載

    本文檔的主要內容詳細介紹的是C語言程序main函數免費下載。
    發表于 09-26 14:48 ?3次下載

    只有潔碧才是全民信賴的水牙線品牌嗎?那可不一定

    身體健康就一定要保證口腔健康。使用水牙線已經是很多西方家庭會使用的清潔口腔內部的辦法,對于國內的消費者來說,水牙線還算是新鮮玩意,所以面對多種多樣的水牙線品牌,覺得只有潔碧,這個水牙線的創始品牌才是值得信賴的,那可不一定
    發表于 04-16 20:31 ?490次閱讀

    C語言的main函數有幾種寫法?

    從學習C語言開始就直寫個函數,那么你知道它的標準寫法什么什么樣嗎? main函數,又稱主函數
    的頭像 發表于 10-15 11:04 ?3325次閱讀

    正確的原理圖不一定能產生正確的 PCB 設計

    作者:黃剛個“xue淋淋”的案例告訴大家:正確的原理圖不一定就能產生正確的PCB設計。原理圖設計與PCB設計都是研發流程中的必經階段,我們知道,原理圖設計是PCB設計的前端流程,之前的案例也分析過個錯誤的原理圖必然會導致
    的頭像 發表于 12-24 13:22 ?2376次閱讀

    STM32程序無法進入main函數的解決方法

    很多人在基于STM32單片機項目開發過程中,會遇到STM32程序無法進入main的現象,在這篇文將分享STM32程序無法進入main函數的解
    的頭像 發表于 07-22 16:18 ?1.6w次閱讀

    D語言編寫單片(STM32F401cc)機應用需要用到的技巧 - 主入口函數

    D語言編寫單片機應用需要用到的技巧 - 主入口函數入口函數入口函數單片機
    發表于 11-29 21:06 ?13次下載
    D語言編寫單片(STM32F401cc)機應用需要用到的技巧 - 主<b class='flag-5'>入口</b><b class='flag-5'>函數</b>

    探究下C語言中main函數各種不同的寫法

    main函數是C程序入口函數,即程序的執行是從main
    發表于 08-07 17:26 ?1146次閱讀
    探究<b class='flag-5'>一</b>下C語言中<b class='flag-5'>main</b><b class='flag-5'>函數</b>各種不同的寫法

    4個并不一定比3個難對付

    4個并不一定比3個難對付
    發表于 11-03 08:04 ?0次下載
    4個并<b class='flag-5'>不一定</b>比3個難對付

    為什么Python沒有main函數

    今天的文章中,我們來討論下為什么有的編程語言有main函數,而Python為什么沒有main函數
    發表于 08-17 11:47 ?335次閱讀

    c語言源程序main函數的位置

    C語言源程序中的main函數程序入口點,它被認為是C語言程序的起點。在執行
    的頭像 發表于 11-24 10:23 ?2608次閱讀

    GD32 MCU啟動后如何運行到main函數

    GD32 MCU啟動后如何運行到main函數入口?你是否也有這樣的疑慮。在執行到main函數之前MCU干了哪些事情呢?下面為大家解答。
    的頭像 發表于 01-15 10:00 ?1097次閱讀
    GD32 MCU啟動后如何運行到<b class='flag-5'>main</b><b class='flag-5'>函數</b>
    主站蜘蛛池模板: 日本漂亮妈妈7观整有限中| 果冻传媒视频在线播放 免费观看| 国产成年人在线观看| 天美传媒色情原创精品| 国产精品免费观看视频播放| 午夜福利电影| 久久99AV无色码人妻蜜| 78m成人亚洲| 四虎永久在线精品国产| 久久AAAA片一区二区| 99久久就热视频精品草| 色偷偷伊人| 精品国产午夜福利在线观看蜜月| 97视频在线免费| 无限资源在线观看完整版免费下载| 精品无码无人网站免费视频| 99久久久久国产精品免费| 无人区乱码1区2区3区网站| 久久夜色噜噜噜亚洲AV0000| 穿着丝袜被男生强行啪啪| 夜里18款禁用的免费B站动漫| 琪琪伦伦影院理论片| 娇妻归来在线观看免费完整版电影 | 一区二区三区福利视频| 欧美深夜0000XXXX疯狂| 韩日美无码精品无码| CHESENGAY痞帅警察GV| 亚洲欧美国产综合在线| 日本久久久久亚洲中字幕| 久久99这里只有精品| 国产成人精选免费视频| 最新无码二区日本专区| 亚洲AV无码乱码国产精品品麻豆 | 国产精品女上位好爽在线短片| 中文字幕完整高清版| 午夜性爽视频男人的天堂在线| 欧美激情精品久久久久| 久久99re2在线视频精品| 国产精品无码亚洲精品| 爆乳啪啪无码成人二区亚洲欧美| 瑜伽牲交AV|