1、第五章汇编语言程序设计及系统初始化第五章汇编语言程序设计及 系统初分别化5.1 ARM汇编语言程序框架汇编语言程序框架5.2 浮点数据处理浮点数据处理5.3 系统初始化系统初始化5.4 中断服务程序中断服务程序本章小结本章小结第五章汇编语言程序设计及系统初始化 5.1 ARM汇编语言程序框架汇编语言程序框架 在MDK环境下,新建一个工程ex5_1,拷贝工程ex4_3中的文件S3C2410A.s和initmemcon.s,然后,编写一个新的汇编语言程序ledflash.s,其代码如下:1 AREA LEDLIGHT, CODE, READONLY2 EXPORT _main ; LedFlash
2、3 EXPORT _use_two_region_memory4 GPCDAT_ADDR EQU 0 x560000245 LED_ON EQU 0 x00006 LED_OFF EQU 0 x00E0第五章汇编语言程序设计及系统初始化7 ENTRY8 ; LedFlash9 _main10 LDR R0, =GPCDAT_ADDR11 MOV R1, #LED_ON 12 STR R1, R0 ; LED ON13 14 BL Delay15 16 MOV R1, #LED_OFF 17 STR R1, R0 ; LED OFF第五章汇编语言程序设计及系统初始化18 19 BL Delay2
3、0 21 B _main22 Delay23 MOV R3, #0 x0F000024 MOV R4, #0 x0F000025 subcycle126 SUB R3, R3, #127 subcycle228 SUB R4, R4, #1第五章汇编语言程序设计及系统初始化29 CMP R4, #030 BGE subcycle231 32 CMP R3, #033 BGE subcycle134 BX LR35 36 _use_two_region_memory ; no warning37 END 将ledflash.s添加到工程ex5_1中,当前工作主窗口如图5-1所示。先不要编译连接这
4、个工程文件,在5.1.2小节时才能正确地编译连接并执行该工程。第五章汇编语言程序设计及系统初始化图5-1 工程ex5_1工作界面第五章汇编语言程序设计及系统初始化5.1.1 通用输入输出通用输入输出C口配置口配置在图5-1中,双击S3C2410A.s打开它,保持其他设置不变(相对于工程ex4_3)的情况下,对I/O Configuration进行配置,如图5-2所示。图5-2中将PC5、PC6和PC7配置为输出特性(Output),对应于S3C2410A.s的第06060608行代码如下:PIOC_SETUP EQU 1PCONC_Val EQU 0 xAAAA56AAPUPC_Val EQU
5、 0 x00000000第五章汇编语言程序设计及系统初始化图5-2 通用I/O口配置第五章汇编语言程序设计及系统初始化PIOC_SETUP为1表示图5-2中的Port C被勾选;当设置PC0PC15如图5-2时,端口C的控制寄存器的值为0 xAAAA56AA;端口C所有上拉电阻都是使能的,端口C上拉控制寄存器的值为0 x00000000。图5-2中的I/O Configuration勾选,对应于S3C2410A.s中的第0510行代码如下:PIO_SETUP EQU 1 如图5-2设置好之后,下面罗列出启动代码文件S3C2410A.s中与通用I/O口配置相关的代码,如表5-1所示。第五章汇编语
6、言程序设计及系统初始化表表5-1 S3C2410A.s中与中与I/O口配置相关的代码口配置相关的代码序号行号注 释 或 语 句10488; I/O Ports definitions20489PIO_BASEEQU0 x56000000; PIO Base Address30490PCONA_OFSEQU0 x00; PCONA Offset40491PCONB_OFSEQU0 x10; PCONB Offset50492PCONC_OFSEQU0 x20; PCONC Offset60493PCOND_OFSEQU0 x30; PCOND Offset70494PCONE_OFSEQU0 x
7、40; PCONE Offset80495PCONF_OFSEQU0 x50; PCONF Offset90496PCONG_OFSEQU0 x60; PCONG Offset100497PCONH_OFSEQU0 x70; PCONH Offset110498PCONJ_OFSEQU0 xD0; PCONJ Offset120499PUPB_OFSEQU0 x18; PUPB Offset第五章汇编语言程序设计及系统初始化130500PUPC_OFSEQU0 x28; PUPC Offset140501PUPD_OFSEQU0 x38; PUPD Offset150502PUPE_OFSEQ
8、U0 x48; PUPE Offset160503PUPF_OFSEQU0 x58; PUPF Offset170504PUPG_OFSEQU0 x68; PUPG Offset180505PUPH_OFSEQU0 x78; PUPH Offset190506PUPJ_OFSEQU0 xD8; PUPJ Offset200509;/ I/O Configuration210510PIO_SETUP EQU12205120536A口注释230537PIOA_SETUPEQU0240538PCONA_ValEQU0 x000003FF2505400565B口注释第五章汇编语言程序设计及系统初始化2
9、60566PIOB_SETUPEQU0270567PCONB_ValEQU0 x000007FF280568PUPB_ValEQU0 x000000002905700605C口注释300606PIOC_SETUPEQU1310607PCONC_ValEQU0 xAAAA56AA320608PUPC_ValEQU0 x000000003306100645D口注释340646PIOD_SETUPEQU0350647PCOND_ValEQU0 x00000000360648PUPD_ValEQU0 x000000003706500685E口注释380686PIOE_SETUPEQU0390687PC
10、ONE_ValEQU0 x00000000第五章汇编语言程序设计及系统初始化序号行号注 释 或 语 句400688PUPE_ValEQU0 x000000004106900709F口注释420710PIOF_SETUPEQU0430711PCONF_ValEQU0 x0000511A440712PUPF_ValEQU0 x000000004507140749G口注释460750PIOG_SETUPEQU0470751PCONG_ValEQU0 x00000000480752PUPG_ValEQU0 x000000004907540779H口注释500780PIOH_SETUPEQU051078
11、1PCONH_ValEQU0 x000007FF520782PUPH_ValEQU0 x00000000第五章汇编语言程序设计及系统初始化530922; I/O Configuration540923IFPIO_SETUP 0550924PIOA_CFG560925DCDPCONA_Val570926PIOB_CFGDCDPCONB_Val580927DCDPUPB_Val590928PIOC_CFGDCDPCONC_Val600929DCDPUPC_Val610930PIOD_CFGDCDPCOND_Val620931DCDPUPD_Val630932PIOE_CFGDCDPCONE_Val
12、第五章汇编语言程序设计及系统初始化640933DCDPUPE_Val650934PIOF_CFGDCDPCONF_Val660935DCDPUPF_Val670936PIOG_CFGDCDPCONG_Val680937DCDPUPG_Val690938PIOH_CFGDCDPCONH_Val700939DCDPUPH_Val710940ENDIF7209811038S3C2410A.s有误,将在下面说明。第五章汇编语言程序设计及系统初始化S3C2410A.s中的第09811038行原始代码如下:IF PIO_SETUP 0 LDR R14, =PIO_BASE IF PIOA_SETUP 0
13、ADR R0, PIOA_CFGSTR R0, R14, #PCONA_OFSENDIF IF PIOB_SETUP 0 ADR R0, PIOB_CFG第五章汇编语言程序设计及系统初始化 LDR R1, R0,#4 STR R0, R14, #PCONB_OFS STR R1, R14, #PUPB_OFS ENDIF IF PIOC_SETUP 0 ADR R0, PIOC_CFG LDR R1, R0,#4 STR R0, R14, #PCONC_OFS STR R1, R14, #PUPC_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOD_SETUP 0 ADR R
14、0, PIOD_CFG LDR R1, R0,#4 STR R0, R14, #PCOND_OFS STR R1, R14, #PUPD_OFS ENDIF IF PIOE_SETUP 0 ADR R0, PIOE_CFG LDR R1, R0,#4 STR R0, R14, #PCONE_OFS STR R1, R14, #PUPE_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOF_SETUP 0 ADR R0, PIOF_CFG LDR R1, R0,#4 STR R0, R14, #PCONF_OFS STR R1, R14, #PUPF_OFS ENDIF IF P
15、IOG_SETUP 0 ADR R0, PIOG_CFG LDR R1, R0,#4 STR R0, R14, #PCONG_OFS STR R1, R14, #PUPG_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOH_SETUP 0 ADR R0, PIOH_CFG LDR R1, R0,#4 STR R0, R14, #PCONH_OFS STR R1, R14, #PUPH_OFS ENDIF ENDIF 修正后的代码如下,其中,添加了注释的为补充和修正的代码行: IF PIO_SETUP 0 LDR R14, =PIO_BASE第五章汇编语言程序设计及系统初始化
16、IF PIOA_SETUP 0 ADR R0, PIOA_CFG LDR R2, R0; Added by ZY STR R2, R14, #PCONA_OFS; Changed by ZY ENDIF IF PIOB_SETUP 0 ADR R0, PIOB_CFG LDR R2, R0; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONB_OFS ; Changed by ZY STR R1, R14, #PUPB_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOC_SETUP 0 ADR R0, PIOC_CFG LDR R2,
17、R0; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONC_OFS; R0,R14, #PCONC_OFS Changed by ZY STR R1, R14, #PUPC_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOD_SETUP 0 ADR R0, PIOD_CFG LDR R2, R0; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCOND_OFS; Changed by ZY STR R1, R14, #PUPD_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOE_SE
18、TUP 0 ADR R0, PIOE_CFG LDR R2, R0; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONE_OFS ; Changed by ZY STR R1, R14, #PUPE_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOF_SETUP 0 ADR R0, PIOF_CFG LDR R2, R0 ; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONF_OFS; Changed by ZY STR R1, R14, #PUPF_OFS ENDIF第五章汇编语言程序设计及系统
19、初始化 IF PIOG_SETUP 0ADR R0, PIOG_CFG LDR R2, R0 ; Added by ZYLDR R1, R0,#4 STR R2, R14, #PCONG_OFS ; Changed by ZY STR R1, R14, #PUPG_OFS ENDIF第五章汇编语言程序设计及系统初始化 IF PIOH_SETUP 0 ADR R0, PIOH_CFG LDR R2, R0 ; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONH_OFS ; Changed by ZY STR R1, R14, #PUPH_OFS ENDIF
20、 ENDIF第五章汇编语言程序设计及系统初始化MDK软件虽然是个极其优秀的软件包,但是,此处的错误是很明显的,由于具有8个IO口,相同的错误连续出现了8次以上。例如对于C口,代码如下:IF PIOC_SETUP 0 ADR R0, PIOC_CFG LDR R1, R0,#4 STR R0, R14, #PCONC_OFS STR R1, R14, #PUPC_OFSENDIF第五章汇编语言程序设计及系统初始化结合第二章,可知条件满足,执行完ADR指令后,R0装入的是PIOC_CFG的标号,即一个地址,这个地址内的值为配置字,但是这个地址本身不能作为配置字,所以,后面的“STR R0, R14
21、, #PCONC_OFS”语句就是完全错误的了。改正的方法很简单,代码如下:IF PIOC_SETUP 0 ADR R0, PIOC_CFGLDR R2, R0 ; Added by ZY LDR R1, R0,#4 STR R2, R14, #PCONC_OFS; R0,R14, #PCONC_OFS Changed by ZY STR R1, R14, #PUPC_OFSENDIF第五章汇编语言程序设计及系统初始化像上述代码一样,将R0值指向的地址处的值赋给R2,然后,再使用“STR R2, R14, #PCONC_OFS”就可以了。对于一个商业软件,其评估版的S3C2410芯片启动代码出
22、现问题,一方面说明了这部分代码没有经过严格测试,另一方面也警告我们,汇编语言编程相对于C语言来说,确有一些劣势。 下面解释一下表5.1和启动代码中关于IO口配置的方法。序号219:定义了IO口存储器映射寄存器的基地址0 x56000000,然后定义了AH口的偏移地址,这些IO口寄存器的地址可参考附表1-1。例如,C口的控制寄存器地址为0 x56000020,相当于基址0 x56000000 + 偏移地址PCONC_OFS(0 x20)。这里没有J口,可以删除。第五章汇编语言程序设计及系统初始化序号21:当勾选了图5-2中I/O Configuration后,此处,PIO_SETUP为1;否则,
23、不勾选时,PIO_SETUP为0,将不初始化IO口。序号2324:由于图5-2中没有勾选Port A,则PIOA_SETUP为0,A口只有控制寄存器,没有上拉寄存器,这里只有PCONA_Val,当然,这个值由于PIOA_SETUP为0而不会被用到。序号2628:由于图5-2中没有勾选Port B,则PIOB_SETUP为0;符号PCONB_Val和PUPB_Val的值表示B口的控制寄存器和上拉寄存器的配置字,这些值随着图形配置向导而自动变化。第五章汇编语言程序设计及系统初始化序号3032:由于图5-2中勾选了Port C,则PIOC_SETUP为1;同时,根据图形配置向导自动设置了控制寄存器和
24、上拉寄存器的值PCONC_Val和PUPC_Val,这两个值代表的含义请参考图5-2和“S3C2410A Users Manual”第九章第10页,把GPC7:5设为输出口。序号3452:介绍端口DH,与上述含义相近,不再重述。序号5471:如果PIO_SETUP不为0,则开辟存储空间存放端口AH的配置字,其中,A口只有一个配置字,BH口均有两个配置字。第五章汇编语言程序设计及系统初始化5.1.2 工程工程ex5_1的注解及运行情况的注解及运行情况在前面5.1.1小节对S3C2410A.s进行修正之后,可以编译连接并下载这个工程了,在编译时会报告一条警告信息,即“ex5_1.sct(8): w
25、arning: L6314W: No section matches pattern *(InRoot$Sections)”,这里的ex5_1.sct是根据工程选项(像图4-15那样)的设置编译工程时自动产生的存储器配置文件,也称Scatter文件,以.sct结尾;“InRoot$Section”是指为连接库里的段分配的空间,用于C语言程序设计中。双击该警告信息,则弹出ex5_1.sct文件内容,如图5-3所示,在“*(InRoot$Sections)”前面加上“;”号将其注释掉,并保存文件。第五章汇编语言程序设计及系统初始化图5-3 ex5_1.sct文件第五章汇编语言程序设计及系统初始化这
26、时先不要编译工程,打开工程选项,选中“Linker”页签,设置如图5-4所示,即使用Scatter File:ex5_1.sct。说明:工程选项中的其他页签保持不变(相对于工程ex4_3)。点击图5-4的“OK”按钮后,可以重新编译工程ex5_1,此时没有错误,也没有警告信息了,如图5-5所示。在图5-5上,点击“Flash | Download”菜单(或单击工具栏上的快捷按钮)则把ex5_1.axf下载到UP-NETARM2410实验箱Nand型Flash上。下载完毕后,程序将启动,可以看到三个LED灯在闪烁!也可以在线仿真调试(一般地,要把程序下载到Flash中后再仿真),或者把ULINK
27、2仿真器从实验箱上取下来,重新给实验箱上电,则程序会从Flash中启动执行。第五章汇编语言程序设计及系统初始化图5-4 工程选项卡设置第五章汇编语言程序设计及系统初始化图5-5 完整的工程ex5_1第五章汇编语言程序设计及系统初始化本节还有两个问题没有解决,其一为Scatter文件如何编写,其二为汇编语言程序ledflash.s的解释。笔者认为Scatter文件的内容及如何编写该文件方面的知识,除了一些ARM官方的文档之外,最好的资料是MDK软件的帮助菜单。这个帮助菜单和它的内容做得相当出色!本书中,笔者几乎无一例外地使用工程选项卡配置存储器,因此,对Scatter文件内容的介绍也不会很多。
28、现在,解释一下5.1节开头给出的程序段,即ledflash.s文件,该文件内容如图5-6所示,在图5-6中给出语句的行号,下面按行号解释。第五章汇编语言程序设计及系统初始化图5-6 ledflash.s文件内容第五章汇编语言程序设计及系统初始化行号01:定义名为LEDLIGHT的只读代码段。行号02:标号_main在外部可见。行号03:标号_use_two_region_memory在外部可见。这句和行号36处没有实际意义,仅是为了编译时不出现警告或错误,因为在S3C2410A.s的第1095行(修正后的文件行号)有一句“IMPORT _use_two_region_memory”。行号04:
29、定义C口数据寄存器地址。行号05:定义LED灯亮的常量。行号06:定义LED灯灭的常量。第五章汇编语言程序设计及系统初始化行号07:ENTRY指程序入口点,一般的汇编程序只需要有一个入口点,而且这个入口点常被用作上电复位后的执行入口点。需要说明的是,这里的ENTRY入口点,并不是上电复位的执行入口点,在本程序中,由于RESET段是存储在地址0 x00000000处的,所以,RESET是上电复位入口点(RESET在S3C2410A.s文件中)。行号09:定义标号_main。行号10:R0 = 0 x56000024。行号11:R1 = 0。行号12:向地址0 x56000024处赋值0,即使GP
30、C5、GPC6和GPC7为0(低电平), 由第二章图2-26可知, 将点亮三个LED灯。第五章汇编语言程序设计及系统初始化行号14:跳转到延迟子程序,这个程序段不作介绍。行号16:R1 = 0 xE0。行号17:向地址0 x56000024处赋值1,即使GPC5、GPC6和GPC7为1(高电平),由第二章图2-26可知,将熄灭三个LED灯。行号19:跳转到延迟子程序。行号21:跳转到_main,循环执行。程序功能:点亮三个LED灯后,等待约(0 xF0000*0 xF0000*指令周期)后,熄灭LED灯,再等待一段时间后,重新点亮LED灯,循环执行,给人LED灯闪烁的感觉。第五章汇编语言程序设
31、计及系统初始化5.1.3 汇编语言语法汇编语言语法ARM汇编语言的语法内容丰容,本书的重点不在于汇编语言,汇编语言主要用于初始化系统。因此,这里简单地介绍一些常用的汇编语言语法。1) AREAAREA已出现在ledflash.s中,用于定义汇编语言代码段或数据段,例如:AREA LEDLIGHT,CODE,READONLYAREA LEDSHINE,DATA,READWRITE第五章汇编语言程序设计及系统初始化上述代码段定义一个名为LEDLIGHT的只读代码段和一个名为LEDSHINE的读写代码段。DATA用得较少。在S3C2410A.s中有如下语句:AREA STACK, NOINIT, R
32、EADWRITE, ALIGN=3该语句中,NOINIT伪关键字表示该段代码只分配空间,不初始化(用0填充),ALIGN=3表示按双字对齐方式(23=8 B)。2) SPACE在S3C2410A.s中有如下语句:Stack_Mem SPACE Stack_Size第五章汇编语言程序设计及系统初始化这里Stack_Mem为标号,Stack_Size为常量,SPACE表示为Stack_Mem分配大小为Stack_Size的连续空间,单位为字节。3) DCDDCD已出现在initmemcon.s中,表示分配字大小的连续空间,并用其他的值初始化该空间,例如:Mem_Val_Conf DCD 0 x22
33、111110, 0 x700表示为标号Mem_Val_Conf分配两个字空间,并初始化这个字的值为0 x22111110和 0 x700。此外,还有DCDU表示不按字对齐方式存储,慎用! 除了DCD之外,还有DCB、DCW、DCQ、DCFS、DCFD等,分别表示为字节、半字、双字、单精度浮点数(即字)、双精度浮点数(即字)分配空间,并使用指定的数据初始化。第五章汇编语言程序设计及系统初始化4) EQUEQU是汇编语言的相等伪指令,用得较多。例如在initmemcon.s中有:Mem_Addr_Base EQU 0 x48000000 5) PRESERVE8PRESERVE8指定当前文件的堆栈
34、采用8字节对齐方式,出现在S3C2410A.s中第0789行,要求每个栈的长度的最低3位为0,且栈底地址的最低3位也应为0。6) ARMARM指示符出现在S3C2410A.s中第0796行,指示编译器生成32位指令的ARM代码;而THUMB指示符表示生成16位指令的Thumb代码。另外,THUMBX用于生成Thumb-2EE代码。第五章汇编语言程序设计及系统初始化7) NOPNOP即No operation,表示空操作。8) IF语句IF语句格式为: IF 条件表达式 语句组1ELSE 语句组2ENDIF第五章汇编语言程序设计及系统初始化当条件表达式为真时,执行语句组1;否则,执行语句组2。出
35、现在条件表达式中的“”(例如S3C2410A.s中的第0923行)表示不等于。表示等于、大于、小于、大于等于、小于等于的关系操作符为=、=、=。9) IMPORTIMPORT后面跟标识符,表明该标识符是在该文件外部定义的,标识符后可以加可选项WEEK,则引用的标识符没有定义时,编译时也不会出错。而该文件中定义的标识符需要被工程中的其他文件引用时,使用EXPORT关键字。同时,GLOBAL可以声明一个全局标识符。此外,EXTERN的功能与IMPORT相似,当该文件中没有实际引用这个标识符时,EXTERN下编译器不会添加该标识符到符号表中。第五章汇编语言程序设计及系统初始化10) 逻辑操作S3C2
36、410A.s的第1054行出现了“:OR:”,表示按位取或,还有以下伪操作符::AND:表示按位取与;:EOR:表示按位取异或;:NOT:表示取反。同时,还有:MOD:表示取模,:SHL:、:SHR:、:ROL:和:ROR:分别表示左移、右移、循环左移、循环右移,还可以使用+、-、*、/算符,其中“+”出现在S3C2410A.s的第1100行。表示逻辑操作的有:LNOT:、:LAND:、:LOR:和:LEOR:,依次为逻辑取反、逻辑与、逻辑或、逻辑异或。第五章汇编语言程序设计及系统初始化11) END汇编语言每个程序段均以END结尾。汇编语言程序是由AREA定义的一个个代码段组成的,每个代码段
37、由汇编指令语句组成,完成某项特定的功能,最后以END结尾。不同的代码段之间可以通过引用标号的方式相互调用。工程ex5_1包含了汇编语言程序的基本特征,可以视为汇编语言程序的学习框架程序。在5.4节中还将添加中断处理进一步完善该程序。第五章汇编语言程序设计及系统初始化5.2 浮点数据处理浮点数据处理浮点数即小数,使用ARM汇编语言表示和处理小数,需要借助于IEEE-754标准或者DSP定标的方法。DSP定标方法在定点DSP芯片进行浮点数据处理时经常使用,相关内容可参考TMS320C5000系列DSP汇编语言程序设计第六章,在这一章中,作者指出,“汇编语言是公认的硬件操作最好的语言,并且用它来编写
38、算法对编程者的思维也是一个很好的启迪过程。”事实上,由于汇编语言语法简单明了,用来实现算法时,没有现成的算法库来调用,因此,编程者必须亲自编写算法的每个函数和每个细节,从而要求编程者对算法非常熟悉才行。本节内容将介绍ARM920T下的数值定标和正余弦函数的计算。第五章汇编语言程序设计及系统初始化5.2.1 计算基础计算基础 计算正弦和余弦函数的值,需要借助于泰勒级数展开式,如下:357111sin3!5!7!xxxxx246111cos12!4!6!xxxx 例如,取x=0.45,则第五章汇编语言程序设计及系统初始化357111sin0.450.450.450.450.453!5!7!2461
39、11cos0.4510.450.450.452!4!6! (1)(2)上两式为本节程序采用的算法。第五章汇编语言程序设计及系统初始化5.2.2 数值定标数值定标汇编语言中的32位操作数只能为0或1组成的码字。所谓“码字”,是指CPU只能把存储器的内容视为二进制数码符号(实际上是电平信号),而不是数字。人们习惯把二进制码字之间的运算关系称为二进制数(二进制补码)之间的运算,所以常常给人一种存储器存储的是数的假象。但是,在码和数之间的确有一种一一映射的关系,并且,在这个映射关系上可以将数的运算映射为码间的运算。同时,由于十六进制表示的整数和码字之间这种映射关系非常直观,以至于人们会忽略这种映射的存
40、在。第五章汇编语言程序设计及系统初始化例如,给定一个十六进制码字0 x00000055,人们会不加思考地认为它等于十进制数85。这种相等是有条件的,即0 x00000055码字的小数定标点位于第0位以后(或认为没有小数定标点),这个定标点是思想中添加的、用于码和数之间映射的一种关系。对于整数的处理,人们可以很直观地认为这个定标点不存在。对于小数处理,就不能忽视这个定标点了。第五章汇编语言程序设计及系统初始化定标的方法就是通过加定标的方法将小数转化为十六进制数(码)的方法,ARM是32位定点处理器,定标点可设为032。定标点确定后,32位的存储字存储的数据大小也就确定了。一个小数a的n定标值为取
41、整(a2n),0n32。根据这种方法,小数0.45的31定标值为0.45231=966367641.6d966367641d=0 x39999999,即设置定标点为31后,十六进制值0 x39999999不再是整数966367641,而是小数0.45。定标有一种记号法,即Q(32n).n,定标点为31时,记作Q1.31,有时简记为Q31,是最常用的一种定标方法。但是,Q31定标只能表示1, 1)区间的小数,如果表示更大范围内的小数,例如区间2, 2),则需要采用定标Q2.30。第五章汇编语言程序设计及系统初始化小数定标后的值往往是小数的近似值,这说明计算机采用定标方法只能不精确地表示小数,例如
42、,小数0.1就不能精确定标。小数的定标值可参与加、减和乘等运算,由于定标值表示的数据范围有限,所以定标值间的运算不能有溢出,否则计算结果错误。特别是乘法运算,乘法结果为64位,定标点位置移动到62位,必须取高32位(同时向左移一位)进行定标点的还原(为31位);加法和减法运算不改变定标点。第五章汇编语言程序设计及系统初始化常用的做法为:在十进制数条件下进行小数的算法处理,找到所有参与运算的小数、中间结果和最终结果的绝对值最大值,按照这个最大值确定定标点位置。然后,将小数转换为定标值,编写汇编语言程序对定标值进行处理,得到定标值表编写汇编语言程序对定标值进行处理,得到定标值表示的最终结果示的最终
43、结果。最后,用去定标的方法,即最终结果除去2n后得到真实的小数形式结果。在这个过程中,只有上一行的阴影部分是ARM汇编语言程序完成的。第五章汇编语言程序设计及系统初始化计算0.45的正弦和余弦值汇编语言程序,由于输入数据、中间结果和最终结果都不可能超过1,可以采用Q31定标方法。需要指出的是,上述介绍的是有符号的定标,即定标值的最高位31位为符号位,这种定标方法用得较多。关于无符号定标方法,由于与有符号定标方法相似,故本书不作介绍。下面把公式(1)和(2)中出现的常数按Q31定标方法计算的定标值列于表5-2中。第五章汇编语言程序设计及系统初始化表表5-2 公式公式(1)和和(2)中常数的中常数
44、的Q31定标值定标值小数0.451/3!1/5!1/7!定标值0 x3999 99990 x1555 55550 x111 11110 x6 8068小数11/2!1/4!1/6!定标值0 x7FFF FFFF0 x4000 00000 x555 55550 x2D 82D8这里的定标点和小数点是完全不同的概念,请注意区分。第五章汇编语言程序设计及系统初始化5.2.3 程序代码及结果分析程序代码及结果分析 本小节的内容不是本书的重点,因此对本小节中的汇编程序不作深入分析,但是我们还是给出了完整的程序示例和源代码(注释清晰),供感兴趣的读者参考。 在工程ex5_1的基础上,新建工程ex5_2,修
45、改ledflash.s文件,其代码如下所示:1 AREA LEDLIGHT, CODE, READONLY2 EXPORT _main ; LedFlash3 EXPORT _use_two_region_memory4 第五章汇编语言程序设计及系统初始化5 IMPORT Sin0p45 ; for Sincos0.456 GPCDAT_ADDR EQU 0 x560000247 LED_ON EQU 0 x00008 LED_OFF EQU 0 x00E09 ENTRY10 ; LedFlash11 _main12 BL Sin0p45 ; for Sincos0.4513 ledflash
46、14 LDR R0, =GPCDAT_ADDR15 MOV R1, #LED_ON 第五章汇编语言程序设计及系统初始化16 STR R1, R0 ; LED ON17 18 BL Delay19 20 MOV R1, #LED_OFF 21 STR R1, R0 ; LED OFF22 23 BL Delay24 25 B ledflash第五章汇编语言程序设计及系统初始化26 Delay27 MOV R3, #0 x0F000028 MOV R4, #0 x0F000029 subcycle130 SUB R3, R3, #131 subcycle232 SUB R4, R4, #133 C
47、MP R4, #034 BGE subcycle235 36 CMP R3, #037 BGE subcycle1第五章汇编语言程序设计及系统初始化38 BX LR39 40 _use_two_region_memory ; no warning41 END 上述代码中后跟注释“; for Sincos0.45”的语句为新添加的语句,即先进行求正余弦值的运算,然后再作使LED灯闪烁的处理。 新建汇编语言文件sincos0p45.s,并添加到工程ex5_2中,工程ex5_2的主界面如图5-7所示。第五章汇编语言程序设计及系统初始化图5-7 工程ex5_2的工作界面第五章汇编语言程序设计及系统初始
48、化文件sincos0p45.s的完整代码如下:1 AREA SINCOS, CODE, READONLY2 EXPORT Sin0p453 Sin0p454 STMFD SP!, R0-R9,R145 6 ; calculate sin0.457 ; R0-R1 load address 8 ; R3-R8 load value9 ADR R0, x_q ; R0 is addr of x第五章汇编语言程序设计及系统初始化10 LDR R4, R0 ; R4 = x11 12 SMULL R5, R6, R4, R413 MOV R7, R6, LSL #114 ADD R7, R7, R5,
49、 LSR #31; R7= x*x15 16 SMULL R5, R6, R4, R717 MOV R8, R6, LSL #118 ADD R8, R8, R5, LSR #31; R8= x*x*x 19 20 ADR R1, cof_3第五章汇编语言程序设计及系统初始化21 LDR R3, R1 ; R3= cof322 23 SMULLR5, R6, R3, R824 MOV R2, R6, LSL #125 ADD R2, R2, R5, LSR #31; R2=x3/3!26 27 MOV R9, R428 SUB R9, R9, R2 ; R9= xx3/3!29 30 SMUL
50、L R5, R6, R7, R831 MOV R8, R6, LSL #1第五章汇编语言程序设计及系统初始化32 ADD R8, R8, R5, LSR #31; R8=x533 34 ADR R1, cof_535 LDR R3, R1; R3= cof536 37 SMULL R5, R6, R3, R838 MOV R2, R6, LSL #139 ADD R2, R2, R5, LSR #31; R2=x5/5!40 41 ADD R9, R9, R2; R9= xx3/3!+x5/5!第五章汇编语言程序设计及系统初始化42 43 SMULL R5, R6, R7, R844 MOV