Use assembly to analyze the Memory Distribution of c code
Use disassembly on the arm platform to analyze the c Memory Distribution: arm: Use the arm-linux-objdump command to decompile the compiled elf File. and then redirect to tmp. s file. the first variable is as follows: c file. vim tmp. c # include
# Define VAR 0 xFFint 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);} Step 2: Compile the Makefile file as follows: vim MakefileCC = arm-linux-gccCFLAGS + =-march = armv7-a Step 3: Compile executable files. then use the make command to compile the file. make tmp generates a tmp elf File. step 4: Use arm-linux-objdump-D tmp> tmp. s // get the following file tmp. s file.: file format elf32-littlearm is extracted as follows: // The following is the corresponding. data Segment-related initialization variables. // variables c, d, and k are all stored in the same region. conclusion: // variables that meet the following requirements are placed. the data segment, that is, the initialized data segment. // all global | static keyword modifier) & Variable not initialized) sassembly of section. data: 00011020 <__ data_start>: 11020: commandid andeqr0, r0, r000011024 <__ dso_handle>: 11024: commandid andeqr0, r0, r000011028
: 11028: 0000000aandeqr0, r0, sl 0001102c
: 1102c: 00000014andeqr0, r0, r4, lsl r000011030
: 11030: 0000000aandeqr0, r0, sl. bss segment. all variables a, B, and f are stored in this region. // The region stores variables that are not initialized or initialized to 0. these variables must meet the following conditions to be placed in the region: (Global | modified by the static keyword) & (initialization | variable initialized to 0) Disassembly of section. bss: 00011034
: 11034: commandid andeqr0, r0, r000011038: 11038: commandid andeqr0, r0, r00001103c
: 1103c: commandid andeqr0, r0, r000011040
: 11040: zookeeper andeqr0, r0, r000011044
: 11044: 00000000andeqr0, r0, r0 // some string constants are stored in this area. in the above c program, "hhhhhhh" corresponds to 686868 ..... // There are also global initialization constants modified using const. the above const int finalone variable. it only corresponds to 848c zookeeper. sassembly of section. rodata: 00008488 <_ IO_stdin_used>: 8488: 00020001andeqr0, r2, r0000848c
: 848c: 0000000aandeqr0, r0, sl8490: 686868681_davsr8 !, {R3, r5, r6, fp, sp, lr} ^ 8494: 6868681_davsr8 !, {R3, r5, r6, fp, sp, lr} ^ 8498: 00000068andeqr0, r0, r8, rrx849c: 20524156subscsr4, r2, r6, asr r184a0: 6379203dstrtvsr2, [r5] #-61; 0x3d84a4: 66202c0astrtvsr2, [r0],-sl, lsl #2484a8: 6c616e69stclvs14, cr6, [r1], #-420; 0xfffffe5c84ac: pushed, r5, pc, ror #2884b0: 62.16203dstrtvsr2, [r5], #-61; 0x3d84b4: 6966202c#dbvsr6 !, {R2, r3, r5, sp} ^ 84b8: 746c616estrbtvcr6, [ip], #-366; 0x16e84bc: 3d206f77stccc15, cr6, [r0, #-476]! 0xfffffe2484c0: pushed, [r4], #-128; 0xffffff8084c4: 203d2068eorscsr2, sp, r8, rrx84c8: 00732520rsbseqr2, r3, r0, lsr #10} // The above also uses # define to declare a macro. where can it be stored. let's take a look at the compilation in main as follows: // The first step is to find out. local variables declared in main. char * hell = "hhhhhhh" // This is the hell variable declaration, 83c0: e3083490movwr3, #33936; 0x8490const int finaltwo = 50; // 83cc: e3a03032movr3, #50; 0x32 // It will be saved in the stack. static int f = 0; static int k = 10; int aa; // The aa variable is optimized by default and does not exist. because it is not used or modified using the volatile keyword, // if the current optimization level of the arm platform is O2 by default, it will exist in the Assembly step. int bb = 10; // 83d4: e3a0300amovr3, #10 This is bb = 10 // This Assembly Code also contains a #255, that is, we use the # define VAR 255 constant, // It is an immediate number. it indicates that it only occupies. text segments, which we often call a code segment. // The following section describes the differences between const and # define constants. limit 83b4
: 83b4: e92d4800push {fp, lr} 83b8: e28db004addfp, sp, # 483bc: pushed, sp, #2483c0: pushed, #33936; 0x849083c4: e3403000movtr3, #083c8: pushed, [fp, #-8] 83cc: Large, #50; 0x3283d0: e50b300cstrr3, [fp, #-12] 83d4: e3a0300amovr3, #1083d8: e50b3010strr3, [fp, #-16] 83dc: pushed, #33948; pushed: e3403000movtr3, #083e4: pushed, #33932; 0x848c83e8: e3402000movtr2, # 083ec: e5922000ldrr2, [r2] 83f0: pushed, [fp, #-8] 83f4: e58d1000strr1, [sp] 83f8: e1a4153movr0, r383fc: e3a010ffmovr1, #255; 0xff8400: e51b300cldrr3, [fp, #-12] 8404: ebffffbcbl82fc <_ init + 0x44> 8408: e1a4243movr0, r3840c: e24bd004subsp, fp, #48410: e8bd8800pop {fp, pc} // parse the differences between define and const. the read-only variables defined by const only provide the corresponding memory address from the assembly point of view, rather than the immediate number given like define. Therefore, the read-only variables defined by const only have one copy during the program running (because it is a global read-only variable stored in the static zone) the macro variables defined by define have several copies in the memory. The define macro is replaced during the pre-compilation phase, while the read-only variables modified by const are determined that the value of define macro has no type during compilation. read-Only variables modified by const have specific types.