程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> 使用匯編分析c代碼的內存分布

使用匯編分析c代碼的內存分布

編輯:關於C
arm平台下使用反匯編分析c內存分布:

arm:使用arm-linux-objdump命令將編譯完成之後的elf文件,進行反匯編.
之後重定向到tmp.s文件中.

第一步變量如下c文件.
vim tmp.c
	
	#include
	
	#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段,也就是初始化數據段.
//所有全局||static關鍵字修飾)&&初始化不為的變量)

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

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

	00011028 :
	11028:	0000000a	andeq	r0, r0, sl      

	0001102c :
	1102c:	00000014	andeq	r0, r0, r4, lsl r0

	00011030 :
	11030:	0000000a	andeq	r0, r0, sl

//下面是對應的.bss段.變量a,b,f都存儲再這個區域.
//該區域存儲的是沒有初始化或者初始化為0的變量.
	這些變量應該滿足如下,條件才會被放到給區域:
	(全局的|被static關鍵字修飾的)&&(為初始化||初始化為0的變量)

	Disassembly of section .bss:
	00011034 :
	11034:	00000000	andeq	r0, r0, r0

	00011038 :
	11038:	00000000	andeq	r0, r0, r0

	0001103c :
	1103c:	00000000	andeq	r0, r0, r0

	00011040 :
	11040:	00000000	andeq	r0, r0, r0

	00011044 :
	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 :
	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變量被默認優化,不存在了.因為沒有被使用,也沒有使用volatile關鍵字修飾,
							  //編譯在當前arm平台下默認優化等級是O2,那麼將將會再匯編中步存在.
	int bb=10;                //83d4:	e3a0300a	mov	r3, #10 這個是bb=10


	//這段匯編代碼中還包含一個#255,也就是我們使用#define VAR 255 常量, 
	//它是一個立即數.說明它只占用.text文本段,也就是我們常說的代碼段.
	//下面由段詳細的解釋:說明const,和#define常量的不同之處.

	000083b4 
: 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修飾的只讀變量具有特定的類型.


  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved