首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

彙編視角解析 C 語言啟動流程:從 _start 到 main

     編輯:關於C語言

彙編視角解析 C 語言啟動流程:從 _start 到 main

為什麼彙編程序入口是 _start,而 C 程序入口是 main?本文通過 gcc 編譯鏈接全過程分析,揭示 crt1.o、crti.o、libc 如何協作完成運行時初始化、調用 main 並處理返回值。

編譯鏈接三部曲

gcc -S main.c    # 1. 預處理+編譯 → main.s (彙編)
gcc -c main.s    # 2. 彙編 → main.o (目標文件)
gcc main.o       # 3. 鏈接 → a.out (可執行文件)
# 實際鏈接命令等價於:
ld /usr/lib/crt1.o /usr/lib/crti.o main.o -lc -dynamic-linker /lib/ld-linux.so.2 -o a.out

關鍵啟動文件符號表

$ nm /usr/lib/crt1.o
U main                 # 未定義,需用戶提供
T _start               # 定義:真正入口點
U __libc_start_main    # libc 初始化函數

$ nm /usr/lib/crti.o
T _init, _fini         # 初始化/終結函數

_start 彙編邏輯 (x86 AT&T)

_start:
    push  %ebp
    mov   %esp, %ebp
    push  $main          # 參數 4: main 地址
    push  $__libc_csu_fini
    push  $__libc_csu_init
    push  $0             # 參數 1: argc (稍後填充)
    push  $0             # 參數 2: argv
    push  $0             # 參數 3: envp
    call  __libc_start_main  # 不返回
    hlt

__libc_start_main(glibc 內部)完成:

  1. 設置 argc/argv/envp;
  2. 調用 _init(構造函數、C++ 全局對象構造);
  3. 調用 main(argc, argv) 獲取返回值 ret;
  4. 調用 _fini(析構函數、atexit 註冊函數);
  5. 調用 exit(ret) 終止進程。

動態鏈接機制

  • __libc_start_main 位於 libc.so.6,**不鏈接進可執行文件**;
  • 可執行文件 .plt (Procedure Linkage Table) 存儲存根代碼,首次調用通過 .got.plt 解析真實地址;
  • 運行時由動態鏈接器 ld-linux.so.2 完成符號綁定。

main 返回值與進程退出碼

// 啟動代碼等價邏輯
exit(main(argc, argv));
  • main 返回 int,傳給 exit();
  • exit() 執行清理(刷新流、調用 atexit)、最終調用 _exit() 系統調用;
  • 退出碼僅 **低 8 位** 有效,Shell 視為無符號數:return -1 → echo $? 輸出 255。

手動鏈接驗證

# 彙編 hello.s (入口 _start, 無 main)
as hello.s -o hello.o
# 鏈接失敗:缺 main 符號
ld hello.o -o hello  # error: undefined reference to 'main'

# 加上 crt1.o 即可(但仍需 main)
ld /usr/lib/crt1.o hello.o -lc -dynamic-linker /lib/ld-linux.so.2 -o hello

總結

  1. _start 是真正入口,由 crt1.o 提供;
  2. 啟動例程 初始化運行環境 → 調用 main → 處理返回值 → exit;
  3. main 是被調用者,而非入口;
  4. 動態鏈接將 libc 初始化推遲到運行時,節省內存與啟動時間。

理解這一流程,對調試啟動崩潰、分析二進制文件、編寫裸機/嵌入式啟動代碼至關重要。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved