使用汇编分析c代码的内存分布

arm平台下使用反汇编分析c内存分布:

arm:使用arm-linux-objdump命令将编译完毕之后的elf文件,进行反汇编.
之后重定向到tmp.s文件里.

第一步变量例如以下c文件.
vim tmp.c
	
	#include<stdio.h>
	
	#define  VAR 0xFF
	
	int a = 0; 
	static int  b =  0;
	
	int c = 10;
	static int  d = 20; 
	
	const int finalone = 10;
	const int final;
	
	int main(void)
	{
	
		char *hell = "hhhhhhh";
		const int finaltwo = 50 ;
		static int f = 0;
		static int k = 10;
		int aa; 
		int bb=10;
		printf("VAR = %d\n, finalone = %d, finaltwo = %d",VAR,finalone,finaltwo);
	}

第二步:编写Makefile文件例如以下
	Makefile文件例如以下:
	vim Makefile
	CC=arm-linux-gcc
	CFLAGS += -march=armv7-a


第三步:编译生成可执行文件.	
	然后使用make命令编译给文件.make tmp 生成tmp elf格式文件.

第四步:
	以下通过使用arm-linux-objdump -D tmp  >  tmp.s

//得到例如以下文件tmp.s文件.

	:     file format elf32-littlearm
	以下是摘出来的相关内如例如以下:

//以下是相应的.data段相关的初始化的变量.
//变量c,d,k都存取再该区域内.结论例如以下:
//须要满足例如以下要求的变量被放在.data段,也就是初始化数据段.
//全部全局||statickeyword修饰)&&初始化不为的变量)

sassembly of section .data: 
	00011020 <__data_start>:
	11020:	00000000	andeq	r0, r0, r0

	00011024 <__dso_handle>:
	11024:	00000000	andeq	r0, r0, r0

	00011028 <c>:
	11028:	0000000a	andeq	r0, r0, sl      

	0001102c <d>:
	1102c:	00000014	andeq	r0, r0, r4, lsl r0

	00011030 <k.1728>:
	11030:	0000000a	andeq	r0, r0, sl

//以下是相应的.bss段.变量a,b,f都存储再这个区域.
//该区域存储的是没有初始化或者初始化为0的变量.
	这些变量应该满足例如以下,条件才会被放到给区域:
	(全局的|被statickeyword修饰的)&&(为初始化||初始化为0的变量)

	Disassembly of section .bss:
	00011034 <completed.5796>:
	11034:	00000000	andeq	r0, r0, r0

	00011038 <a>:
	11038:	00000000	andeq	r0, r0, r0

	0001103c <b>:
	1103c:	00000000	andeq	r0, r0, r0

	00011040 <f.1727>:
	11040:	00000000	andeq	r0, r0, r0

	00011044 <final>:
	11044:	00000000	andeq	r0, r0, r0


//这个区域存放了一些字符串常量.如上c程序中的 "hhhhhhh"相应的686868.....
//还有使用const修饰的全局初始化的常量.如上面的const int finalone变量.它的仅仅相应的是848c的00000000a.	
	sassembly of section .rodata:

	00008488 <_IO_stdin_used>:
	8488:	00020001	andeq	r0, r2, r1

	0000848c <finalone>:
	848c:	0000000a	andeq	r0, r0, sl
	8490:	68686868	stmdavs	r8!, {r3, r5, r6, fp, sp, lr}^
	8494:	68686868	stmdavs	r8!, {r3, r5, r6, fp, sp, lr}^
	8498:	00000068	andeq	r0, r0, r8, rrx
	849c:	20524156	subscs	r4, r2, r6, asr r1
	84a0:	6425203d	strtvs	r2, [r5], #-61	; 0x3d
	84a4:	66202c0a	strtvs	r2, [r0], -sl, lsl #24
	84a8:	6c616e69	stclvs	14, cr6, [r1], #-420	; 0xfffffe5c
	84ac:	20656e6f	rsbcs	r6, r5, pc, ror #28
	84b0:	6425203d	strtvs	r2, [r5], #-61	; 0x3d
	84b4:	6966202c	stmdbvs	r6!, {r2, r3, r5, sp}^
	84b8:	746c616e	strbtvc	r6, [ip], #-366	; 0x16e
	84bc:	3d206f77	stccc	15, cr6, [r0, #-476]!	; 0xfffffe24
	84c0:	2c642520	cfstr64cs	mvdx2, [r4], #-128	; 0xffffff80
	84c4:	203d2068	eorscs	r2, sp, r8, rrx
	84c8:	00732520	rsbseq	r2, r3, r0, lsr #10}

//上面还使用#define声明一个宏.它存储再哪里呢.我们能够看一下啊main中的汇编例如以下:
//第一步找出.在main中声明的局部变量.
	char *hell = "hhhhhhh"	  //这个是hell变量的声明,83c0:	e3083490	movw	r3, #33936	; 0x8490
	const int finaltwo = 50 ; // 83cc:	e3a03032	mov	r3, #50	; 0x32 //它会被保存的栈中.
	static int f = 0;
	static int k = 10;
	int aa;                   //aa变量被默认优化,不存在了.由于没有被使用,也没有使用volatilekeyword修饰,
							  //编译在当前arm平台下默认优化等级是O2,那么将将会再汇编中步存在.
	int bb=10;                //83d4:	e3a0300a	mov	r3, #10 这个是bb=10


	//这段汇编代码中还包括一个#255,也就是我们使用#define VAR 255 常量, 
	//它是一个马上数.说明它仅仅占用.text文本段,也就是我们常说的代码段.
	//以下由段具体的解释:说明const,和#define常量的不同之处.

	000083b4 <main>:
	83b4:	e92d4800	push	{fp, lr}
	83b8:	e28db004	add	fp, sp, #4
	83bc:	e24dd018	sub	sp, sp, #24
	83c0:	e3083490	movw	r3, #33936	; 0x8490
	83c4:	e3403000	movt	r3, #0
	83c8:	e50b3008	str	r3, [fp, #-8]
	83cc:	e3a03032	mov	r3, #50	; 0x32
	83d0:	e50b300c	str	r3, [fp, #-12]
	83d4:	e3a0300a	mov	r3, #10
	83d8:	e50b3010	str	r3, [fp, #-16]
	83dc:	e308349c	movw	r3, #33948	; 0x849c
	83e0:	e3403000	movt	r3, #0
	83e4:	e308248c	movw	r2, #33932	; 0x848c
	83e8:	e3402000	movt	r2, #0
	83ec:	e5922000	ldr	r2, [r2]
	83f0:	e51b1008	ldr	r1, [fp, #-8]
	83f4:	e58d1000	str	r1, [sp]
	83f8:	e1a00003	mov	r0, r3
	83fc:	e3a010ff	mov	r1, #255	; 0xff
	8400:	e51b300c	ldr	r3, [fp, #-12]
	8404:	ebffffbc	bl	82fc <_init+0x44>
	8408:	e1a00003	mov	r0, r3
	840c:	e24bd004	sub	sp, fp, #4
	8410:	e8bd8800	pop	{fp, pc}
	
//解析define和const的不同之处.	
	const 定义的仅仅读变量从汇编角度来看 仅仅是给出了相应的内存地址 
	而不是像define一样给出的是马上数 所以 const定义的仅仅读变量在程序执行过程中仅仅有一份拷贝
	(由于它是全局的仅仅读变量 存放在静态区) 而define定义的宏变量在内存中有若干个拷贝 define宏是在预编译阶段进行替换 
	而const修饰的仅仅读变量是在编译的时候确定其值 define宏没有类型 而const修饰的仅仅读变量具有特定的类型.


posted @ 2017-05-26 18:46  yfceshi  阅读(340)  评论(0编辑  收藏  举报