深入瞭解C語言(區域性變數的定義) (轉)

worldblog發表於2007-12-12
深入瞭解C語言(區域性變數的定義) (轉)[@more@]

深入瞭解C語言

這一節我們主要來研究一下C語言如何使用中的區域性變數的.C語言中對於全域性變數和區域性變數所分配的空間地址是不一樣的.全域性變數是放在_DATA段,也就是除開_TEXT程式碼段的另一塊集中的空間.而區域性變數主要是使用堆疊的記憶體空間.好了,讓我們直接看看下面這個案例研究.

研究案例三

工具: Turboc C v2.0,De,MASM v5.0,NASM
例項C:
/* example3.c */
char ch;

int e_main()
{
int i1;
int i2;
int i3;
i1=1;
i2=2;
i3=3;

}

; C程式的入口 start.asm
[BITS 16]
[global start]
[extern _e_main]
start:
  call _e_main

目標內容:C語言使用區域性變數的方法

同樣,這裡我需要使用start.asm來作為我們C語言的入口.我們使用e_main,避開常規main函式入口,這樣我們就能更清晰地瞭解到函式內部所產生的程式碼指令.

跟前一節一樣,我們先編譯C程式和入口匯序start.asm
nasmw -f obj -o start.obj start.asm
TCC -mt -oexample3.obj -c example3.c
link start.obj example3.obj,example3.exe,,,
exe2bin example3.exe

同樣,我們使用老DOS的DEBUG工具來對example3.bin進行反檢視C生成的程式碼.

DEBUG
-n example3.bin
-l 0
-u 0
xxxx:0000 CALL 0003
xxxx:0003 PUSH BP
xxxx:0004 MOV BP,SP
xxxx:0006 SUB  SP,+06
xxxx:0009 MOV  PTR [BP-06],
0001
xxxx:000E MOV WORD PTR [BP-04],
0002
xxxx:0014 MOV WORD PTR [BP-02],
0003
xxxx:0019 MOV  SP,BP
xxxx:001B  POP BP
xxxx:001C  RET

好了,這裡關於C生成的程式碼已經顯露出來了.除開第一句CALL 0003是我們在start.asm的程式碼外,其它就是我C程式生成的程式碼.
首先進入e_main函式.

PUSH BP
MOV  BP,SP
這跟我們前面第二個案例中函式反問引數的程式碼相同.先儲存BP,然後把堆疊指標傳遞給BP,以便後面透過BP來實現對變數的訪問.

SUB  SP,+06
將堆疊指標繼續後移動6個位元組.因為我們在e_main中定義三個整型變數i1,i2,i3,一共6個位元組的空間.這裡透過移動堆疊指標,來實現區域性變數的記憶體空間分配.

MOV  WORD PTR [BP-06],0001
MOV WORD PTR [BP-04],0002
MOV  WORD PTR [BP-02],0003
分別對應我們在e_main中的三條賦值語句
i1=1;
i2=2;
i3=3;
這裡我們可以看出,i1的地址實際上就是BP-06,i2就是BP-04,i3就是BP-02.前面的SUB SP,+06就是為了這三個變數而留出6個位元組的空間(BP-08到BP-02)
同時我們也看到C語言中16位的賦值語句就是簡單的MOV指令完成的.

MOV  SP,BP
當e_main函式結束後,堆疊指標還原成BP(BP值從未改變過).這樣,我們的區域性變數i1,i2,i3的空間也就消失了.所以當C語言中的函式結束後,函式中的區域性變數會自動消失.

POP  BP
還原BP的值.這與前面的PUSH BP想對應

好了,本案例研究完畢.下面是總結的時候了.
C語言函式中的區域性變數的空間一般都是放在堆疊裡面.在進入函式前,透過"SUB SP,+XX"來為這些區域性變數分配堆疊空間.然後同樣透過BP來對這些區域性變數進行訪問.函式結束時,"MOV SP,BP"還原堆疊指標,區域性變數隨之而消失.最後以"POP BP"還原BP,結束該函式.

值得注意的是,C語言會自動為C函式中經常使用int型別變數設定成resigter int.這樣的區域性變數就不是使用堆疊空間的了,而就是直接使用SI暫存器.
比如一個典型的例子
void l()
{
 int i;
 while(i<10000)
 {
  i++;
 }
}
對於這樣的函式,C語言通常會將i成resigter int i.這個i沒有使用任何記憶體空間來儲存數值,它的數值直接儲存於SI暫存器.那麼對它的訪問速度自然比起一般的變數要快.


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992331/,如需轉載,請註明出處,否則將追究法律責任。

相關文章