代碼段和堆棧

代碼段:架構

在採用段式內存管理的架構中,代碼段(code segment / text segment)一般是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經肯定,而且內存區域一般屬於只讀, 某些架構也容許代碼段爲可寫,即容許程序自我修改(self-modifying code)。 在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。ide

操做系統在裝載一個程序時會進行進程地址空間的分段,而代碼段一般處於最底部,即最低地址部分,而堆和棧在高處,因此在容許代碼段可寫的架構上,當堆或棧內存溢出時,代碼段中的數據就會開始被覆蓋。函數

 

通常來講,能夠簡單地理解爲內存分爲三個部分:靜態區,棧,堆。spa

 

不少地方沒有把把堆和棧解釋清楚,致使老是分不清楚。其實堆棧就是棧,而不是堆。堆的英文是heap;棧的英文是stack,也翻譯爲堆棧。堆和棧都有本身的特性,這裏先不作討論。操作系統

 

靜態區:保存自動全局變量和static 變量(包括static 全局和局部變量)。靜態區的內容在總個程序的生命週期內都存在,由編譯器在編譯的時候分配。.net

 

棧(stack):棧又稱堆棧, 是用戶存放程序臨時建立的局部變量,也就是說咱們函數括弧「{}」中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此之外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,而且待到調用結束後,函數的返回值也會被存放回棧中。因爲棧的先進先出特色,因此棧特別方便用來保存/恢復調用現場。從這個意義上講,咱們能夠把堆棧當作一個寄存、交換臨時數據的內存區。翻譯

棧上的內容只在函數的範圍內存在,當函數運行結束,這些內容也會自動被銷燬。其特色是效率高,但空間大小有限。rest

 

堆(heap):code

堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc系列函數或new 操做符分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);其生命週期由free 或delete 決定。當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。在沒有釋放以前一直存在,直到程序結束。其特色是使用靈活,空間比較大,但容易出錯。生命週期

 

 

程序:

/* stack07.c */

int foo() {

    int a;

    int b;

    int c;

   

    a = 2;

    b = 3;

    c = 4;

 

    return 0;

}

 

int main(int argc, char * argv[]) {

    foo();

    return 0;

}

 

彙編:

    TITLE    stack07.c

    .386P

include listing.inc

if @Version gt 510

.model FLAT

else

_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'

_TEXT    ENDS

_DATA    SEGMENT DWORD USE32 PUBLIC 'DATA'

_DATA    ENDS

CONST    SEGMENT DWORD USE32 PUBLIC 'CONST'

CONST    ENDS

_BSS    SEGMENT DWORD USE32 PUBLIC 'BSS'

_BSS    ENDS

_TLS    SEGMENT DWORD USE32 PUBLIC 'TLS'

_TLS    ENDS

FLAT    GROUP _DATA, CONST, _BSS

    ASSUME    CS: FLAT, DS: FLAT, SS: FLAT

endif

PUBLIC    _foo

_TEXT    SEGMENT

_a$ = -4

_b$ = -8

_c$ = -12

_foo    PROC NEAR

 

; 2    : int foo() {

 

  00000    55         push     ebp

  00001    8b ec         mov     ebp, esp

  00003    83 ec 0c     sub     esp, 12            ; 0000000cH

 

; 3    :     int a;

; 4    :     int b;

; 5    :     int c;

; 6    :    

; 7    :     a = 2;

 

  00006    c7 45 fc 02 00

    00 00         mov     DWORD PTR _a$[ebp], 2

 

; 8    :     b = 3;

 

  0000d    c7 45 f8 03 00

    00 00         mov     DWORD PTR _b$[ebp], 3

 

; 9    :     c = 4;

 

  00014    c7 45 f4 04 00

    00 00         mov     DWORD PTR _c$[ebp], 4

 

; 10   :

; 11   :     return 0;

 

  0001b    33 c0         xor     eax, eax

 

; 12   : }

 

  0001d    8b e5         mov     esp, ebp

  0001f    5d         pop     ebp

  00020    c3         ret     0

_foo    ENDP

_TEXT    ENDS

PUBLIC    _main

_TEXT    SEGMENT

_main    PROC NEAR

 

; 14   : int main(int argc, char * argv[]) {

 

  00021    55         push     ebp

  00022    8b ec         mov     ebp, esp

 

; 15   :     foo();

 

  00024    e8 00 00 00 00     call     _foo

 

; 16   :     return 0;

 

  00029    33 c0         xor     eax, eax

 

; 17   : }

 

  0002b    5d         pop     ebp

  0002c    c3         ret     0

_main    ENDP

_TEXT    ENDS

END

 

AT彙編

    .file    "stack07.c"

    .text

    .globl    _foo

    .def    _foo;    .scl    2;    .type    32;    .endef

_foo:

LFB0:

    .cfi_startproc

    pushl    %ebp

    .cfi_def_cfa_offset 8

    .cfi_offset 5, -8

    movl    %esp, %ebp

    .cfi_def_cfa_register 5

    subl    $16, %esp

    movl    $2, -4(%ebp)

    movl    $3, -8(%ebp)

    movl    $4, -12(%ebp)

    movl    $0, %eax

    leave

    .cfi_restore 5

    .cfi_def_cfa 4, 4

    ret

    .cfi_endproc

LFE0:

    .def    ___main;    .scl    2;    .type    32;    .endef

    .globl    _main

    .def    _main;    .scl    2;    .type    32;    .endef

_main:

LFB1:

    .cfi_startproc

    pushl    %ebp

    .cfi_def_cfa_offset 8

    .cfi_offset 5, -8

    movl    %esp, %ebp

    .cfi_def_cfa_register 5

    andl    $-16, %esp

    call    ___main

    call    _foo

    movl    $0, %eax

    leave

    .cfi_restore 5

    .cfi_def_cfa 4, 4

    ret

    .cfi_endproc

LFE1:

    .ident    "GCC: (GNU) 5.3.0"

 

(完)

相關文章
相關標籤/搜索