深入瞭解C語言(區域性變數的定義) (轉)
深入瞭解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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C語言--靜態區域性變數C語言變數
- C語言區域性變數、全域性變數、靜態區域性變數、靜態全域性變數C語言變數
- c 語言中巨集定義和定義全域性變數的區別變數
- 【c】全域性變數與區域性變數變數
- 函式之定義及全域性變數&區域性變數&風溼理論函式變數
- 在 C 中引用匯編語言定義的 .globl 變數變數
- C/C++定義全域性變數/常量幾種方法的區別C++變數
- c語言中的變數儲存區域C語言變數
- C# WebForm定義全域性變數C#WebORM變數
- Python全域性變數與區域性變數詳解Python變數
- 詳解python 區域性變數與全域性變數Python變數
- C語言裡全域性變數管理C語言變數
- 全域性變數與區域性變數變數
- 區域性變數和全域性變數變數
- javascript中的作用域(全域性變數和區域性變數)JavaScript變數
- 第四節 go 語言變數定義Go變數
- 酒店房間和 C++ 區域性變數的作用域C++變數
- Java區域性變數與全域性變數Java變數
- java 全域性變數和區域性變數Java變數
- JavaScript —— 區域性變數和全域性變數JavaScript變數
- jmeter全域性變數和區域性變數JMeter變數
- 成員變數和區域性變數的區別變數
- C語言(巨集定義)C語言
- C 語言的變數作用域及標頭檔案變數
- python全域性變數與區域性變數Python變數
- Go 語言變數作用域Go變數
- Python中的全域性變數和區域性變數Python變數
- js-js的全域性變數和區域性變數JS變數
- C語言可變引數詳解C語言
- 成員變數和區域性變數變數
- c語言的定義與宣告C語言
- 深入瞭解視覺語言模型視覺模型
- JavaScript五:全域性變數&區域性變數;運算子JavaScript變數
- python全域性變數和區域性變數, globalPython變數
- Python的區域性變數和全域性變數使用解惑Python變數
- [ASM C/C++] C語言函式的可選性自變數ASMC++C語言函式變數
- Python的全域性和區域性變數Python變數
- Python中類變數、成員變數、區域性變數的區別Python變數