Linux C下变量和常量的存储的本质

源代码

#cat main.c
#include <stdio.h>

int i = 100;

int main(void)
{
	func();
	return 0;
}
#cat func.c
#include <stdio.h>

extern i;

int yyyy;
char *s1 = "hello world\n";

int func()
{
	static int j = 200;
	static int wwwww = 300;
	printf("i:%d\n",i);
	printf("wwww:%d\n",wwwww);
	return 0;
}
gcc -o main func.c main.c

变量的存储

变量s1 存储在 .data里;

#readelf -s main
    61: 0000000000601050     0 NOTYPE  GLOBAL DEFAULT   25 _end
    62: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start
    63: 0000000000601038     8 OBJECT  GLOBAL DEFAULT   24 s1
    64: 0000000000601034     4 OBJECT  GLOBAL DEFAULT   24 i
#readelf -S main
  [23] .got.plt          PROGBITS         0000000000601000  00001000
       0000000000000030  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000601030  00001030
       0000000000000018  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000601048  00001048

常量的存储

hello world 存储在哪里? 我们知道是 rodata里,看看位置吧:

#objdump -d -j .rodata main

main:     file format elf64-x86-64


Disassembly of section .rodata:

0000000000400600 <_IO_stdin_used>:
  400600:	01 00 02 00 00 00 00 00                             ........

0000000000400608 <__dso_handle>:
	...
  400610:	68 65 6c 6c 6f 20 77 6f 72 6c 64 0a 00 69 3a 25     hello world..i:%
  400620:	64 0a 00 77 77 77 77 3a 25 64 0a 00                 d..wwww:%d..

结合反汇编

#objdump -D main > main.s

这里看到s1的位置是601038 , 查看main.s

#readelf -s main
    61: 0000000000601050     0 NOTYPE  GLOBAL DEFAULT   25 _end
    62: 0000000000400440     0 FUNC    GLOBAL DEFAULT   13 _start
    63: 0000000000601038     8 OBJECT  GLOBAL DEFAULT   24 s1
    64: 0000000000601034     4 OBJECT  GLOBAL DEFAULT   24 i
#vim main.s
0000000000601038 <s1>:
  601038:   10 06                   adc    %al,(%rsi)
  60103a:   40 00 00                add    %al,(%rax)
  60103d:   00 00                   add    %al,(%rax)
    ...

const 全局变量

const 可以将变量存储在哪里? - rodata

这里,应该明白 const修饰后的变量,存储在rodata段,自然不能更改;

指针本质

#cat main.c
#include <stdio.h>

int i = 10;
int *p = &i;

int func(void)
{
	return 0;
}

int main(void)
{
	i = 20;
	*p = 30;
	return 0;
}
#gcc -o main  main.c

汇编:

#objdump -D main > main.s

查看符号表:

func函数的地址是:4004ed, 知道这个地址后,看汇编代码

#readelf -s main
    54: 00000000004005a8     0 OBJECT  GLOBAL HIDDEN    15 __dso_handle
    55: 00000000004005a0     4 OBJECT  GLOBAL DEFAULT   15 _IO_stdin_used
    56: 00000000004004ed    11 FUNC    GLOBAL DEFAULT   13 func
    57: 0000000000400520   101 FUNC    GLOBAL DEFAULT   13 __libc_csu_init
    58: 0000000000601048     0 NOTYPE  GLOBAL DEFAULT   25 _end
    59: 0000000000400400     0 FUNC    GLOBAL DEFAULT   13 _start

其实,看到汇编,可以明白,一个函数名,也是一个地址;

#vim main.s
00000000004004ed <func>:   // 函数名func 的地址是4004ed
  4004ed:   55                      push   %rbp
  4004ee:   48 89 e5                mov    %rsp,%rbp
  4004f1:   b8 00 00 00 00          mov    $0x0,%eax
  4004f6:   5d                      pop    %rbp
  4004f7:   c3                      retq

00000000004004f8 <main>:
  4004f8:   55                      push   %rbp
  4004f9:   48 89 e5                mov    %rsp,%rbp
  4004fc:   c7 05 2a 0b 20 00 14    movl   $0x14,0x200b2a(%rip)        # 601030 <i>
  400503:   00 00 00
  400506:   48 8b 05 2b 0b 20 00    mov    0x200b2b(%rip),%rax        # 601038 <p>
  40050d:   c7 00 1e 00 00 00       movl   $0x1e,(%rax)
  400513:   b8 00 00 00 00          mov    $0x0,%eax
  400518:   5d                      pop    %rbp
  400519:   c3                      retq
  40051a:   66 0f 1f 44 00 00       nopw   0x0(%rax,%rax,1)```
posted @ 2019-02-19 12:12  苏小北1024  阅读(473)  评论(0编辑  收藏  举报