static变量存放在.data还是.bss 来⾃:
#include <stdio.h>
void add()
{
static int var;
var++;
printf("var=%d\n",var);
}static修饰的变量
int main()
{
add();
return 0;
}
/*
//汇编之后
.file "seeStatic.c"
.local var.0
m 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
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定义所特有的,表⽰虽然放在全局区域但是不可导出
m 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
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的⼤⼩
m 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 $0x8,%esp
6: 83 e4 f0 and $0xfffffff0,%esp
9: b8 00 00 00 00 mov $0x0,%eax
e: 29 c4 sub %eax,%esp
10: 83 ec 0c sub $0xc,%esp
13: 6a 10 push $0x10
15: e8 fc ff ff ff call 16 <main+0x16>;
1a: 83 c4 10 add $0x10,%esp
1d: 89 45 fc mov %eax,0xfffffffc(%ebp)
20: a1 00 00 00 00 mov 0x0,%eax
25: a3 00 00 00 00 mov %eax,0x0
2a: a3 04 00 00 00 mov %eax,0x4
2f: 83 ec 08 sub $0x8,%esp
32: 8d 45 fc lea 0xfffffffc(%ebp),%eax
35: 50 push %eax
36: 68 05 00 00 00 push $0x5 //对应.LC1
3b: e8 fc ff ff ff call 3c <main+0x3c>;
//为什么⼀样的⼆进制代码和下⼀个printf调⽤翻译出来的汇编不⼀样见4e地址处
//⽤objdump -r 查看了⼀下,发现printf是需要重定位的,但是应该重定向到同⼀位置
//为什么会出现地址不⼀样的情况,请⾼⼿解答
40: 83 c4 10 add $0x10,%esp
43: 83 ec 08 sub $0x8,%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 $0x10,%esp
56: c9 leave
57: c3 ret
*/
从中学习到了 static 声明的变量,不管它是全局变量也好,还是在函数之中的也好,只要是没有赋初值 都存放在.bss段,如果赋了初值,则把它放在.data段。
反汇编的⽅法, ⾸先
gcc -o test.o -c test.c
得到test.o⽂件,然后,objdump -d test.o 即可。