static 变量存放在.data还是.bss

#include <stdio.h>

void add()
{
static   int   var;
var++;
printf(“var=%d\n”,var);

}

int main()
{
add();
return 0;
}

/*
//汇编之后
.file    “seeStatic.c”
.local    var.0
.comm    var.0,4,4
.section    .rodata
.LC0:
.string    “var=%d\n”
.text
.globl add
.type    add,@function
add:
pushl    %ebp
movl    %esp, %ebp
subl    $8, %esp
incl    var.0
subl    $8, %esp
pushl    var.0
pushl    $.LC0
call    printf
addl    $16, %esp
leave
ret
.Lfe1:
.size    add,.Lfe1-add
.globl main
.type    main,@function
main:
pushl    %ebp
movl    %esp, %ebp
subl    $8, %esp
andl    $-16, %esp
movl    $0, %eax
subl    %eax, %esp
call    add
movl    $0, %eax
leave
ret
.Lfe2:
.size    main,.Lfe2-main
.ident    “GCC: (GNU) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)”
*/
//———————————————————————————————————————————————
/*网上的 资料

ChinaUnix.net

gerysand    2005-4-15 04:24
关于堆,栈,动态分配,静态分配的一个小实验

其中有些不明白,大家帮着解释一下

下边是c源码
char *str_g=”abcd”;
int a=0;
int b;
int main()
{
static int c;
char *str_l=(char *)malloc(16);
c=b=a;
printf(“address of str_l=%x\n”,&str_l);
printf(“address of malloc string=%x\n”,str_l);
}

gerysand    2005-4-15 04:51
关于堆,栈,动态分配,静态分配的一个小实验

编译后的汇编
.file   “test.c”        //指出这个文件由test.c编译而来
.section        .rodata //只读段包含字符”abcd”
.LC0:
.string “abcd”

.globl str_g            //全局变量str_g
.data           //表明在数据段中
.align 4
.type   str_g, @object
.size   str_g, 4
str_g:
.long   .LC0    //初始化为.LC0的地址,即”abcd”字符串的地址
.globl a                //全局变量a
.bss            //为什么它放在bss数据段中?(还是我理解的有问题)
.align 4
.type   a, @object
.size   a, 4
a:
.zero   4       //长度为4个字节,初始化为0(是这个意思吗?)
.local c.0     //用local标记的static变量c,这个是static定义所特有的,表示虽然放在全局区域但是不可导出
.comm   c.0,4,4 //用comm标记应该是表示未初始化,但是后边0,4,4表示什么无从考证
.section        .rodata //又是两个字符串常量,用rodata标记为只读数据段
.LC1:
.string “address of str_l=%x\n” //.LC1长度为21byte
.LC2:
.string “address of malloc string=%x\n”
.text
.globl main             //全局函数入口
.type   main, @function
main:
pushl   %ebp
movl    %esp, %ebp
subl    $8, %esp
andl    $-16, %esp
movl    $0, %eax
subl    %eax, %esp
subl    $12, %esp
pushl   $16
call    malloc
addl    $16, %esp
movl    %eax, -4(%ebp)
movl    a, %eax
movl    %eax, b
movl    %eax, c.0
subl    $8, %esp
leal    -4(%ebp), %eax
pushl   %eax
pushl   $.LC1
call    printf
addl    $16, %esp
subl    $8, %esp
pushl   -4(%ebp)
pushl   $.LC2
call    printf
addl    $16, %esp
leave
ret
.size   main, .-main    //计算main的大小
.comm   b,4,4           //为什么b放在这里定义???难道它是放在text段里吗???comm应该是指未初始化
.section        .note.GNU-stack,”",@progbits
.ident “GCC: (GNU) 3.3.2 20031022 (Red Hat Linux 3.3.2-1)”

用bojdump -d 查看的.o文件

test.o:     文件格式 elf32-i386

反汇编 .text 节:

00000000 <main>;:
0:   55                      push   %ebp
1:   89 e5                   mov    %esp,%ebp
3:   83 ec 08                sub    $0×8,%esp
6:   83 e4 f0                and    $0xfffffff0,%esp
9:   b8 00 00 00 00          mov    $0×0,%eax
e:   29 c4                   sub    %eax,%esp
10:   83 ec 0c                sub    $0xc,%esp
13:   6a 10                   push   $0×10
15:   e8 fc ff ff ff          call   16 <main+0×16>;
1a:   83 c4 10                add    $0×10,%esp
1d:   89 45 fc                mov    %eax,0xfffffffc(%ebp)
20:   a1 00 00 00 00          mov    0×0,%eax
25:   a3 00 00 00 00          mov    %eax,0×0
2a:   a3 04 00 00 00          mov    %eax,0×4
2f:   83 ec 08                sub    $0×8,%esp
32:   8d 45 fc                lea    0xfffffffc(%ebp),%eax
35:   50                      push   %eax
36:   68 05 00 00 00          push   $0×5 //对应.LC1
3b:   e8 fc ff ff ff          call   3c <main+0x3c>;
//为什么一样的二进制代码和下一个printf调用翻译出来的汇编不一样???见4e地址处
//用objdump -r 查看了一下,发现printf是需要重定位的,但是应该重定向到同一位置
//为什么会出现地址不一样的情况,请高手解答
40:   83 c4 10                add    $0×10,%esp
43:   83 ec 08                sub    $0×8,%esp
46:   ff 75 fc                pushl 0xfffffffc(%ebp)
49:   68 1a 00 00 00          push   $0x1a //对应.LC2,和LC1相差21byte
4e:   e8 fc ff ff ff          call   4f <main+0x4f>;
53:   83 c4 10                add    $0×10,%esp
56:   c9                      leave
57:   c3                      ret

*/

从中学习到了 static 声明的变量,不管它是全局变量也好,还是在函数之中的也好,只要是没有赋初值
都存放在.bss段,如果赋了初值,则把它放在.data段。

反汇编的方法, 首先
gcc -o test.o -c test.c
得到test.o文件,然后,objdump -d test.o 即可。

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>