代码段和堆栈

代码段:架构

在采用段式内存管理的架构中,代码段(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"

 

(完)

相关文章
相关标签/搜索