代码段和堆栈

代码段:

在采用段式内存管理的架构中,代码段(code segment / text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许程序自我修改(self-modifying code)。 在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

操作系统在装载一个程序时会进行进程地址空间的分段,而代码段通常处于最底部,即最低地址部分,而堆和栈在高处,所以在允许代码段可写的架构上,当堆或栈内存溢出时,代码段中的数据就会开始被覆盖。

 

一般来说,可以简单地理解为内存分为三个部分:静态区,栈,堆。

 

很多地方没有把把堆和栈解释清楚,导致总是分不清楚。其实堆栈就是栈,而不是堆。堆的英文是heap;栈的英文是stack,也翻译为堆栈。堆和栈都有自己的特性,这里先不做讨论。

 

静态区:保存自动全局变量和static 变量(包括static 全局和局部变量)。静态区的内容在总个程序的生命周期内都存在,由编译器在编译的时候分配。

 

栈(stack):栈又称堆栈, 是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但空间大小有限。

 

堆(heap):

堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用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"

 

(完)

 

转载于:https://my.oschina.net/dubenju/blog/803706

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值