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

使用反組譯分析 C 語言記憶體分佈:ARM 平台實戰指南

     編輯:關於C

前言

在嵌入式開發中,理解 C 程式編譯後的記憶體佈局至關重要。本文將透過 ARM 平台下的反組譯工具 arm-linux-objdump,深入剖析變量在不同記憶體段(.data、.bss、.rodata、.text)中的分佈規律,並對比 const 與 #define 的本質區別。

實驗環境與準備

1. 原始碼準備

建立測試檔案 tmp.c,包含各類型變量:

#include <stdio.h>
#define VAR 0xFF

int a = 0;                 // 全域初始化為 0
static int b = 0;          // 靜態全域初始化為 0
int c = 10;                // 全域初始化非 0
static int d = 20;         // 靜態全域初始化非 0
const int finalone = 10;   // 全域常量初始化
const int final;           // 全域常量未初始化

int main(void) {
    char *hell = "hhhhhhh";      // 字串字面量
    const int finaltwo = 50;     // 局部常量
    static int f = 0;            // 靜態局部初始化為 0
    static int k = 10;           // 靜態局部初始化非 0
    int aa;                      // 局部未初始化(優化掉)
    int bb = 10;                 // 局部初始化非 0
    printf("VAR = %d\n, finalone = %d, finaltwo = %d", VAR, finalone, finaltwo);
    return 0;
}

2. 編譯腳本

編寫 Makefile:

CC=arm-linux-gcc
CFLAGS += -march=armv7-a

執行 make tmp 生成 ELF 執行檔 tmp。

3. 反組譯輸出

使用命令 arm-linux-objdump -D tmp > tmp.s 獲取完整反組譯列表,以下節選關鍵段落。

記憶體段分析

.data 段:已初始化的全域/靜態變量

Disassembly of section .data:
00011020 <__data_start>:
00011028 <c>:        0000000a
0001102c <d>:        00000014
00011030 <k.1728>:  0000000a

結論:c、d、k 均為「全域或 static 修飾」且「初始值非 0」的變量,故置於 .data 段。

.bss 段:未初始化或初始化為 0 的全域/靜態變量

Disassembly of section .bss:
00011038 <a>:
0001103c <b>:
00011040 <f.1727>:
00011044 <final>:

結論:a、b、f、final 滿足「全域或 static」且「未初始化或初值為 0」,歸屬 .bss 段。

.rodata 段:唯讀資料(字串常量、const 全域常量)

Disassembly of section .rodata:
0000848c <finalone>:  0000000a
00008490:            68686868  ...  // "hhhhhhh" ASCII 碼

說明:字串字面量 "hhhhhhh" 及 const int finalone 存放於 .rodata,屬唯讀區域。

.text 段:程式碼與立即數(宏定義)

反組譯 main 函數片段:

000083fc: e3a010ff  mov r1, #255 ; 0xff  // #define VAR 0xFF 直接作為立即數嵌入指令
000083cc: e3a03032  mov r3, #50  ; 0x32  // const int finaltwo = 50 存入棧區

關鍵差異:

  • #define 宏在預處理階段直接文本替換,編譯時成為指令中的立即數,佔用 .text 段,每處使用皆產生一份拷貝。
  • const 變量在編譯期確定值,存放於靜態區(.rodata 或棧),運行期僅有一份拷貝,且具備型別檢查。

總結對照表

變量類型記憶體段條件
全域/靜態 + 初值非 0.data已初始化資料段
全域/靜態 + 未初始化或初值 0.bss未初始化資料段
字串常量、全域 const 初始化.rodata唯讀資料段
#define 宏.text立即數嵌入指令碼
局部 const棧運行期棧幀分配

結語

透過反組譯可直觀掌握 C 語言變量的記憶體佈局,對嵌入式系統優化、除錯及安全性分析極具指導意義。理解 const 與 #define 的底層差異,有助於編寫更高效、可維護的程式碼。

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