您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 国内外标准规范 > 编译器对RW和ZI的处理
课题名称:编译器对RW和ZI的处理姓名:安钢学号:103229一、实验目的:C编译器在编译连接C程序时,一般是将程序分成代码段,初始化数据段,未初始化数据段,这三个段通常是在存储器中分开放置,但又有一些规律,即代码段放在一个位置,未初始化数据段是紧接着初始化数据段之后。本实验的目的主要就是为了验证编译器的这种处理方式。二、实验步骤2.1实验程序设计为了研究程序在储存器中存储位置的规律,设计了一个简单的函数如下,函数有如下特点,(1)为了便于跟踪反汇编,以说明问题更深层次的方面,main函数里使用了内嵌汇编,(2)对编译器设置了code地址和数据地址,具体设置如下图(3)设置了几个简单变量,例子简单但能够更深入的分析问题的本质。以上特点都是为了说清楚反汇编的处理。上图重点在ROBASE=0X8000RWBASE=0X10000后面将会看到此设置的意义。实验程序如下:#includestdio.hintSPACE,WI,LO=15,WI1=6,WI2=10;voidmain(void){__asm{addWI,WI1,WI2mulSPACE,LO,WI}//return(SPACE);}如示,设置了未定义的SPACE,WI和定义了的LO=15,WI1=6,WI2=10后面的反汇编将说明每一个变量在存储器中应存放的精确地址。2.2反汇编的处理为了方便说明,主要分析放在代码的注释部分,结论性的分析将放在代码后面,;编译器自动的预先处理;注意此处是从0x00008000开始执行对照上面所作设置。。。__main[0xe28f8090]addr8,pc,#0x90;#0x8098;跳到_region_table;那里放了4个编译器系统设置的4个常量00008004[0xe898000f]ldmiar8,{r0-r3};将4个量放入R0--R3,00008008[0xe0800008]addr0,r0,r80000800c[0xe0811008]addr1,r1,r800008010[0xe0822008]addr2,r2,r800008014[0xe0833008]addr3,r3,r800008018[0xe240b001]subr11,r0,#1;R11=R0--10000801c[0xe242c001]subr12,r2,#1;R12=R2--1_move_region[0xe1500001]cmpr0,r100008024[0x0a00000e]beq_zero_region;R0=R1时跳到_zero_region00008028[0xe8b00070]ldmiar0!,{r4-r6};若R0!=R1将R0指向的内容放入;r4-r6同时R0指针更新0000802c[0xe1540005]cmpr4,r5;若R4=R5,跳回到_move_region00008030[0x0afffffa]beq_move_region00008034[0xe3140001]tstr4,#1;测试R4第0位是否为100008038[0x1084400b]addner4,r4,r11;若不为1则R4=R4+R110000803c[0xe3150001]tstr5,#1;测试R5第0位是否为100008040[0x1085500b]addner5,r5,r11;若不为1则R5=R5+R1100008044[0xe3150002]tstr5,#2;测试R5第1位是否为100008048[0x10855009]addner5,r5,r9;若不为1则R5=R5+R90000804c[0xe3c55003]bicr5,r5,#3;清除R5的第0,1位的1_move_loop[0xe2566004]subsr6,r6,#4;R6=R6--400008054[0x24947004]ldrcsr7,[r4],#4;大于等于00008058[0x24857004]strcsr7,[r5],#40000805c[0x8afffffb]bhi_move_loop;大于00008060[0xeaffffee]b_move_region_zero_region[0xe1520003]cmpr2,r3;R2=R3时跳到__rt_entry/******注此处添加__rt_entry后面的部分代码。。。。。。。__rt_entry[0xeb00004d]bl__rt_stackheap_init;由函数名知是堆栈初始化000080e4[0xeb00000d]bl__rt_lib_init;由函数名知是关于库的初始化000080e8[0xebffffee]blmain;初始化完成后,即进程环境初始化后,跳到main处;BL表示main完后还会跳回来000080ec[0xea000005]bexit;MAIN执行完,执行exit//UNIX系统中,main进程执行前G编译器要进行例行处理,以获得命令行参数和环境表,执行完main后自动执行exit以关闭I/O流,释放进程的资源其调用形式形如EXIT(main(argc,argv));可见ADS的编译器与UNIX大同小异*/*****//此处以分析过main执行完的处理,故后面将略去相关分析。。。。//接_zero_region[0xe1520003]cmpr2,r300008068[0x0b00001c]bleq__rt_entry0000806c[0xe3a07000]movr7,#0;R2!=R3时00008070[0xe8b20030]ldmiar2!,{r4,r5};基本同上分析00008074[0xe3140001]tstr4,#100008078[0x1084400c]addner4,r4,r120000807c[0xe3140002]tstr4,#200008080[0x10844009]addner4,r4,r900008084[0xe3c44003]bicr4,r4,#3_zero_loop[0xe2555004]subsr5,r5,#40000808c[0x24847004]strcsr7,[r4],#400008090[0x8afffffc]bhi_zero_loop00008094[0xeafffff2]b_zero_region;跳回到_zero_region_region_table[0x00000310]dcd0x00000310....0000809c[0x00000334]dcd0x000003344...000080a0[0x00000334]dcd0x000003344...000080a4[0x0000034c]dcd0x0000034cL...;可见以上4个常量就是说明编译器如何存放代码和数据段的;下面的分析将更加直观;程序主流程从这里开始;与前面的设置对应可以很清晰的看到初始化了的变量存放在#0x00010000处,和设置的一样!!!Main[0xe59f1020]*ldrr1,0x000080d0;=#0x00010000;R1=初始化数据区000080ac[0xe9910005]ldmibr1,{r0,r2};初始化数据区前两个数取出来&R1+8000080b0[0xe0800002]addr0,r0,r2;相加WI1+WI2=R0R1指向LO000080b4[0xe59f2018]ldrr2,0x000080d4;=#0x0001000c;指针到第13字节000080b8[0xe5820004]strr0,[r2,#4];R0存入第17字节处即WI处;完成了addWI,WI1,WI2;此时R1指向LOr2,指向SPACE;R0=WI000080bc[0xe5911000]ldrr1,[r1,#0];将初始化数据区中的LO取出000080c0[0xe0000091]mulr0,r1,r0;MULWI,LO,WI000080c4[0xe5820000]strr0,[r2,#0];将WI存入未初始化变量区的SPACE;至此程序主流程已完成;这前后大都是编译器自动的处理,前面已有简单的分析,故略去。3实验结论C编译器在编译连接C程序时,一般是将程序分成代码段,初始化数据段,未初始化数据段,这三个段通常是在存储器中分开放置,但又有一些规律,即代码段放在一个位置,未初始化数据段是紧接着初始化数据段之后。本实验主要验证了编译器的这种处理方式。
本文标题:编译器对RW和ZI的处理
链接地址:https://www.777doc.com/doc-2141214 .html