从一个实例的vs2005汇编代码分析变量在段上的分配--数据段,代码段,BSS段

来源:互联网 发布:js cookie使用 编辑:程序博客网 时间:2024/04/27 20:35
 

BSS段:BSS段(bss segment)通常是指用来存放程序中未初始化的全局变量的一块内存区域。BSS是英文Block Started by Symbol的简称。BSS段属于静态内存分配。

数据段:数据段(data segment)通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

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

堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

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

上述知识,通过一个小程序的汇编代码可以进行验证,源程序如下:

++++++++++++++++++++++++++++++

int global1[1000];
int global2[1000]={1,2,3,4,5};
const int global3=1;
#include "stdio.h"
int main()
{
 static int static_int1;
    static int static_int2=1;
 int integer1;
 int integer2=1;
 char *char_ptr="ABCD";
 const int const_integer2=1;
 printf("static_int1:%d/n",static_int1);
 printf("integer2:%d,/n",integer2);
 printf("const_integer2:%d,/n",const_integer2);
 printf("global3:%d,/n",global3);
}

+++++++++++++++++++++++++++++++

在VS2005下,汇编出来的代码如下:

; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.762

 TITLE c:/Documents and Settings/Administrator.EMPIRIX-7A1AC0B/My Documents/Visual Studio 2005/Projects/test3/test3/test3.cpp
 .686P
 .XMM
 include listing.inc
 .model flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC ?global1@@3PAHA     ; global1
PUBLIC ?global2@@3PAHA     ; global2
_BSS SEGMENT
?global1@@3PAHA DD 03e8H DUP (?)   ; global1
_BSS ENDS

_DATA SEGMENT
?global2@@3PAHA DD 01H     ; global2
 DD 02H
 DD 03H
 DD 04H
 DD 05H
 ORG $+3980
?static_int2@?1??main@@9@4HA DD 01H   ; `main'::`2'::static_int2
_DATA ENDS
PUBLIC ??_C@_0N@DOIGNOHI@global3?3?$CFd?0?6?$AA@ ; `string'
PUBLIC ??_C@_0BE@LHDBCOKP@const_integer2?3?$CFd?0?6?$AA@ ; `string'
PUBLIC ??_C@_0O@NJGPOKNP@integer2?3?$CFd?0?6?$AA@ ; `string'
PUBLIC ??_C@_08KIMNCGGL@test?3?$CFd?6?$AA@  ; `string'
PUBLIC ??_C@_04ILJKFADF@ABCD?$AA@   ; `string'
PUBLIC _main
EXTRN __imp__printf:PROC
EXTRN __RTC_CheckEsp:PROC
EXTRN __RTC_Shutdown:PROC
EXTRN __RTC_InitBase:PROC
_BSS SEGMENT
?static_int1@?1??main@@9@4HA DD 01H DUP (?)  ; `main'::`2'::static_int1
_BSS ENDS
; COMDAT ??_C@_0N@DOIGNOHI@global3?3?$CFd?0?6?$AA@
; File c:/documents and settings/administrator.empirix-7a1ac0b/my documents/visual studio 2005/projects/test3/test3/test3.cpp
CONST SEGMENT
??_C@_0N@DOIGNOHI@global3?3?$CFd?0?6?$AA@ DB 'global3:%d,', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_0BE@LHDBCOKP@const_integer2?3?$CFd?0?6?$AA@
CONST SEGMENT
??_C@_0BE@LHDBCOKP@const_integer2?3?$CFd?0?6?$AA@ DB 'const_integer2:%d,', 0aH
 DB 00H      ; `string'
CONST ENDS
; COMDAT ??_C@_0O@NJGPOKNP@integer2?3?$CFd?0?6?$AA@
CONST SEGMENT
??_C@_0O@NJGPOKNP@integer2?3?$CFd?0?6?$AA@ DB 'integer2:%d,', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_08KIMNCGGL@test?3?$CFd?6?$AA@
CONST SEGMENT
??_C@_08KIMNCGGL@test?3?$CFd?6?$AA@ DB 'test:%d', 0aH, 00H ; `string'
CONST ENDS
; COMDAT ??_C@_04ILJKFADF@ABCD?$AA@
CONST SEGMENT
??_C@_04ILJKFADF@ABCD?$AA@ DB 'ABCD', 00H  ; `string'
CONST ENDS
; COMDAT rtc$TMZ
rtc$TMZ SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ ENDS
; COMDAT rtc$IMZ
rtc$IMZ SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ ENDS
; COMDAT _main
_TEXT SEGMENT
_const_integer2$ = -44     ; size = 4
_char_ptr$ = -32     ; size = 4
_integer2$ = -20     ; size = 4
_main PROC      ; COMDAT

; 7    : {

 push ebp
 mov ebp, esp
 sub esp, 240    ; 000000f0H
 push ebx
 push esi
 push edi
 lea edi, DWORD PTR [ebp-240]
 mov ecx, 60     ; 0000003cH
 mov eax, -858993460    ; ccccccccH
 rep stosd

; 8    :  static int static_int1;
; 9    :     static int static_int2=1;
; 10   :  int integer1;
; 11   :  int integer2=1;

 mov DWORD PTR _integer2$[ebp], 1

; 12   :  char *char_ptr="ABCD";

 mov DWORD PTR _char_ptr$[ebp], OFFSET ??_C@_04ILJKFADF@ABCD?$AA@

; 13   :  const int const_integer2=1;

 mov DWORD PTR _const_integer2$[ebp], 1

; 14   :  printf("test:%d/n",static_int1);

 mov esi, esp
 mov eax, DWORD PTR ?static_int1@?1??main@@9@4HA
 push eax
 push OFFSET ??_C@_08KIMNCGGL@test?3?$CFd?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 15   :  printf("integer2:%d,/n",integer2);

 mov esi, esp
 mov eax, DWORD PTR _integer2$[ebp]
 push eax
 push OFFSET ??_C@_0O@NJGPOKNP@integer2?3?$CFd?0?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 16   :  printf("const_integer2:%d,/n",const_integer2);

 mov esi, esp
 push 1
 push OFFSET ??_C@_0BE@LHDBCOKP@const_integer2?3?$CFd?0?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 17   :  printf("global3:%d,/n",global3);

 mov esi, esp
 push 1
 push OFFSET ??_C@_0N@DOIGNOHI@global3?3?$CFd?0?6?$AA@
 call DWORD PTR __imp__printf
 add esp, 8
 cmp esi, esp
 call __RTC_CheckEsp

; 18   : }

 xor eax, eax
 pop edi
 pop esi
 pop ebx
 add esp, 240    ; 000000f0H
 cmp ebp, esp
 call __RTC_CheckEsp
 mov esp, ebp
 pop ebp
 ret 0
_main ENDP
_TEXT ENDS
END
+++++++++++++++++++++++++++++++++++++++++++++++

未初始化的全局变量global1,分配在BSS段,该段只保存分配的内存空间的大小,初始值自动设为0。初始化的全局变量global2和初始化的静态局部变量static_int2放到DATA段,const global3放到const段中,注意若无 printf("global3:%d,/n",global3);则该变量不会出现在汇编代码中,会被VS2005优化掉;static_int1放到BSS段中,但同样注意若无 printf("static_int1:%d,/n",static_int1);则该变量不会出现在汇编代码中,会被VS2005优化掉;integer2const_integer2都是栈上的局部变量,再分配空间上没发现不同,但在使用时,前者通过偏移量,得到变量值,而后者处理类似常量,通过立即数直接得到值,这也证明了“c++中的const常量,默认情况下是内部连接的,并且不分配内存空间,而只是在符号表里存储一份拷贝。”,另外需注意,如没有使用变量的语句--如本例子中的printf,则出全局变量之外的变量都会被优化掉。

原创粉丝点击