C程式的儲存空間布局(二)

2021-06-20 06:32:05 字數 2545 閱讀 5333

c程式的儲存空間布局(二)

void

foo()

}

使用gcc -c生成目標檔案後利用objdump -d反彙編一下,生成如下:

0:   push

%rbp

1: mov

%rsp,%rbp

4: movl $0x0,-0x4(%rbp)

b:jmp1e

d:mov

-0x4(%rbp),%eax

10: cltq

12: movl $0x0,-0x20(%rbp,%rax,4)1

a:addl $0x1,-0x4(%rbp)

1e:cmpl $0x4,-0x4(%rbp)

22: jle

d 24: pop

%rbp

25: retq

觀察一下此彙編**知:對i賦值的語句是 movl $0x0,-0x4(%rbp) ,對陣列a元素賦值的語句是movl $0x0,-0x20(%rbp,%rax,4) 。其中$0x0對應整數0自然不必多說,而%rbp則代表棧底位址暫存器,%rax我覺得應該是暫存器%eax的最低32位(我是64位機子,%eax也應是64位的),結合前面的**知道這裡就**著i的值。有此認識後,變數i的位址 -0x4(%rbp) 意義也就清晰了,它位於棧底!而陣列i的位址 -0x20(%rbp,%rax,4) 可解析為:%rbp-0x20+%rax*4,也就是說,陣列a的位址是 -0x20(%rbp)。(注:第一眼看到這我就懵了,這樣的話a[4]不正代表著i嗎?因為(20-4)/4=4。後來突然意識到,0x20是16進製制數。。。)於是乎,棧的分布圖如下:

-0x4

i-0x8

-0xc

-0x10

-0x14

a[3]

-0x18

a[2]

-0x1c

a[1]

-0x20

a[0]

哈,奇怪吧。變數i跟陣列a之間竟然存在一段空白!那麼,這段空白裡面竟然存在有什麼資料呢?我一開始也不明白,還以為是apue裡面說的函式呼叫時所需要儲存的資訊。後來覺得這還是說不通,因為這些資訊應該位於i的上面才是。看著這張表,我想起了struct結構體的變數對齊問題,覺得這兩者之中貌似有些類似啊。於是我往函式裡面又增加了乙個變數,果斷不是所料,新增加的變數被放入-0x8的位置!那麼,如果這段空白已經被填滿了,再加乙個變數情況又會變成什麼樣呢?答案是:棧的空間又增加了0x10的大小,然後,棧會變成這個樣子:

-0x4

i-0x8

j-0xc

k-0x10

l-0x14

m-0x18

-0x1c

-0x20

-0x24

a[3]

-0x28

a[2]

-0x2c

a[1]

-0x30

a[0]

(可能你還會想那麼變數i,j,k...是怎麼安排的,雖然我沒做過驗證,但我想應該跟他們宣告的順序以及有沒有被初始化有關)

至此,為什麼foo函式在我這不會發生死迴圈的原因應該算是清楚了。而對於把陣列a跟變數i放在foo函式外面的情況,其反彙編出來的**是:

0:   push   %rbp

1: mov %rsp,%rbp

4: movl $0x0,0x0(%rip)

e: jmp 32 10: mov 0x0(%rip),%eax

16: cltq

18: movl $0x0,0x0(,%rax,4)

23: mov 0x0(%rip),%eax

29: add $0x1,%eax

2c: mov %eax,0x0(%rip)

32: mov 0x0(%rip),%eax

38: cmp $0x4,%eax

3b: jle 10 3d: pop %rbp

3e: retq

有能力的同學自己分析下看看了,我彙編基礎不大好,所以還是有些不明白%rip是什麼玩意。不過,實驗中我曾經列印過a跟i的位址,發現i總會比a大0x10,故a[4]的位址即是i的位址。

為什麼編譯器會這樣安排呢?我認為,跟結構體的記憶體對齊是同個道理。具體可參考:

最後的最後,不妨再給出一段**,讓大家猜猜輸出結果會是什麼 。(實踐出真知,不妨執行一下,看與你想的一不一樣)

#include 

int glob_v1;

int glob_v2;

int glob_array[4];

int glob_v1_with_value = 1

;int glob_v2_with_value = 2

;int glob_array_with_value[4] = ;

int main(int

argc, const char *argv)

c程式儲存空間布局

摘自 c程式一直由下面幾部分組成 1 棧 由編譯器自動分配釋放管理。區域性變數及每次函式呼叫時返回位址 以及呼叫者的環境資訊 例如某些機器暫存器 都存放在棧中。新被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,c函式可以遞迴 呼叫。遞迴函式每次呼叫自身時,就使用乙個新的棧幀,...

c程式儲存空間布局

摘自 c程式一直由下面幾部分組成 1 棧 由編譯器自動分配釋放管理。區域性變數及每次函式呼叫時返回位址 以及呼叫者的環境資訊 例如某些機器暫存器 都存放在棧中。新被呼叫的函式在棧上為其自動和臨時變數分配儲存空間。通過以這種方式使用棧,c函式可以遞迴 呼叫。遞迴函式每次呼叫自身時,就使用乙個新的棧幀,...

C程式的儲存空間布局

下午突然想到了c程式的儲存空間布局,忘了,翻書溫習,記錄如下 乙個c程式的組成 正文段,初始化資料段 資料段 非初始化資料段 bss 棧,堆 下面簡單介紹下這些段 正文段 由cpu執行的機器指令部分。通常,正文段是可共享的,在儲存器中只需要有乙個副本即可,很多時候,正文段也是唯讀的,防止意外修改 初...