1、ARM 应用系统开发详解基于 S3C4510B 的系统设计 1第 4 章 ARM 程序设计基础ARM编译器一般都支持汇编语言的程序设计和 C/C+语言的程序设计,以及两者的混合编程。本章介绍 ARM程序设计的一些基本概念,如 ARM汇编语言的伪指令、汇编语言的语句格式和汇编语言的程序结构等,同时介绍 C/C和汇编语言的混合编程等问题。本章的主要内容: ARM编译器所支持的伪指令 汇编语言的语句格式 汇编语言的程序结构 相关的程序示例4.1 ARM 汇编器所支持的伪指令在 ARM 汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,通常称这些特殊指令助记符
2、为伪指令,他们所完成的操作称为伪操作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。在 ARM 的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。4.1.1 符号定义(Symbol Definition)伪指令符号定义伪指令用于定义 ARM 汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。常见的符号定义伪指令有如下几种: 用于定义全局变量的 GBLA、GBLL 和 GBLS。 用于定义局部变量的 LCLA、LCLL 和 LCLS。 用于对变量赋值的 SETA、
3、SETL、SETS。 为通用寄存器列表定义名称的 RLIST。1、 GBLA、GBLL 和 GBLS语法格式:GBLA(GBLL 或 GBLS) 全局变量名GBLA、GBLL 和 GBLS 伪指令用于定义一个 ARM 程序中的全局变量,并将其初始化。其中:GBLA 伪指令用于定义一个全局的数字变量,并初始化为 0;GBLL 伪指令用于定义一个全局的逻辑变量,并初始化为 F(假);GBLS 伪指令用于定义一个全局的字符串变量,并初始化为空;由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。使用示例:GBLA Test1 ;定义一个全局的数字变量,变量名为 Test1Test
4、1 SETA 0xaa ;将该变量赋值为 0xaaGBLL Test2 ;定义一个全局的逻辑变量,变量名为 Test2Test2 SETL TRUE ;将该变量赋值为真GBLS Test3 ;定义一个全局的字符串变量,变量名为 Test3ARM 应用系统开发详解基于 S3C4510B 的系统设计 2Test3 SETS “Testing” ;将该变量赋值为“Testing”2、 LCLA、LCLL 和 LCLS语法格式:LCLA(LCLL 或 LCLS) 局部变量名LCLA、LCLL 和 LCLS 伪指令用于定义一个 ARM 程序中的局部变量,并将其初始化。其中:LCLA 伪指令用于定义一个局
5、部的数字变量,并初始化为 0;LCLL 伪指令用于定义一个局部的逻辑变量,并初始化为 F(假);LCLS 伪指令用于定义一个局部的字符串变量,并初始化为空;以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。使用示例:LCLA Test4 ;声明一个局部的数字变量,变量名为 Test4Test3 SETA 0xaa ;将该变量赋值为 0xaaLCLL Test5 ;声明一个局部的逻辑变量,变量名为 Test5Test4 SETL TRUE ;将该变量赋值为真LCLS Test6 ;定义一个局部的字符串变量,变量名为 Test6Test6 SETS “Testing” ;将该变量赋值为
6、“Testing”3、 SETA、SETL 和 SETS语法格式:变量名 SETA(SETL 或 SETS) 表达式伪指令 SETA、SETL、SETS 用于给一个已经定义的全局变量或局部变量赋值。SETA 伪指令用于给一个数学变量赋值;SETL 伪指令用于给一个逻辑变量赋值;SETS 伪指令用于给一个字符串变量赋值;其中,变量名为已经定义过的全局变量或局部变量,表达式为将要赋给变量的值。使用示例:LCLA Test3 ;声明一个局部的数字变量,变量名为 Test3Test3 SETA 0xaa ;将该变量赋值为 0xaaLCLL Test4 ;声明一个局部的逻辑变量,变量名为 Test4Te
7、st4 SETL TRUE ;将该变量赋值为真4、 RLIST语法格式:名称 RLIST 寄存器列表RLIST 伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在 ARM 指令 LDM/STM 中使用。在 LDM/STM 指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。使用示例:RegList RLIST R0-R5,R8,R10 ;将寄存器列表名称定义为 RegList,可在 ARM指令LDM/STM中通过该名称访问寄存器列表。4.1.2 数据定义(Data Definition )伪指令数据定义伪指令一般用于为特定的数据分配存储单
8、元,同时可完成已分配存储单元的初始化。常见的数据定义伪指令有如下几种: DCB 用于分配一片连续的字节存储单元并用指定的数据初始化。 DCW(DCWU ) 用于分配一片连续的半字存储单元并用指定的数据初始化。 DCD(DCDU) 用于分配一片连续的字存储单元并用指定的数据初始化。 DCFD(DCFDU)用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初ARM 应用系统开发详解基于 S3C4510B 的系统设计 3始化。 DCFS(DCFSU) 用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。 DCQ(DCQU) 用于分配一片以 8 字节为单位的连续的存储单元并用指定
9、的数据初始化。 SPACE 用于分配一片连续的存储单元 MAP 用于定义一个结构化的内存表首地址 FIELD 用于定义一个结构化的内存表的数据域1、 DCB语法格式:标号 DCB 表达式DCB 伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为 0255 的数字或字符串。DCB 也可用“=”代替。使用示例:Str DCB “This is a test!” ;分配一片连续的字节存储单元并初始化。2、 DCW(或 DCWU)语法格式:标号 DCW(或 DCWU) 表达式DCW(或 DCWU)伪指令用于分配一片连续的半字存储单元并用伪指令中指定的表达式初始化。其
10、中,表达式可以为程序标号或数字表达式。用 DCW 分配的字存储单元是半字对齐的,而用 DCWU 分配的字存储单元并不严格半字对齐。使用示例:DataTest DCW 1,2,3 ;分配一片连续的半字存储单元并初始化。3、 DCD(或 DCDU)语法格式:标号 DCD(或 DCDU) 表达式DCD(或 DCDU)伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。DCD 也可用“*; Institute of Automation,Chinese Academy of Sciences;Description: This example sh
11、ows the UART communication!;Author: JuGuang,Lee;Date:;*UARTLCON0 EQU 0x3FFD000UARTCONT0 EQU 0x3FFD004UARTSTAT0 EQU 0x3FFD008UTXBUF0 EQU 0x3FFD00CUARTBRD0 EQU 0x3FFD014AREA Init,CODE,READONLYENTRY;*;LED Display;*LDR R1,=0x3FF5000LDR R0,=*;UART0 line control register;*LDR R1,=UARTLCON0LDR R0,=0x03ARM
12、应用系统开发详解基于 S3C4510B 的系统设计 15STR R0,R1;*;UART0 control regiser;*LDR R1,=UARTCONT0LDR R0,=0x9STR R0,R1;*;UART0 baud rate divisor regiser;Baudrate=19200,对应于 50MHz的系统工作频率;*LDR R1,=UARTBRD0LDR R0,=0x500 STR R0,R1;*;Print the messages!;*LOOPLDR R0,=Line1BL PrintLineLDR R0,=Line2BL PrintLineLDR R0,=Line3BL
13、 PrintLineLDR R0,=Line4BL PrintLineLDR R1,=0x7FFFFFLOOP1SUBS R1,R1,#1BNE LOOP1B LOOP;*;Print line ;*PrintLineMOV R4,LRMOV R5,R0LineLDRB R1,R5,#1AND R0,R1,#*; Institute of Automation, Chinese Academy of Sciences ;File Name: Init.s;Description:;Author: JuGuang,Lee;Date:;*IMPORT Main ;通知编译器该标号为一个外部标号AR
14、EA Init,CODE,READONLY ;定义一个代码段ENTRY ;定义程序的入口点LDR R0,=0x3FF0000 ;初始化系统配置寄存器,具体内容可参考第五、六章LDR R1,=0xE7FFFF80STR R1,R0LDR SP,=0x3FE1000 ;初始化用户堆栈,具体内容可参考第五、六章BL Main ;跳转到 Main()函数处的 C/C+代码执行END ;标识汇编程序的结束以上的程序段完成一些简单的初始化,然后跳转到 Main()函数所标识的 C/C代码处执行主要的任务,此处的 Main 仅为一个标号,也可使用其他名称,与 C 语言程序中的 main()函数没有关系。/*
15、 Institute of Automation, Chinese Academy of Sciences ARM 应用系统开发详解基于 S3C4510B 的系统设计 17* File Name: main.c* Description: P0,P1 LED flash. * Author: JuGuang,Lee* Date:*/void Main(void)int i;*(volatile unsigned long *) 0x3ff5000) = 0x0000000f;while(1)*(volatile unsigned long *) 0x3ff5008) = 0x00000001;for(i=0; i0x7fFFF; i+);*(volatile unsigned long *) 0x3ff5008) = 0x00000002;for(i=0; i0x7FFFF; i+);4.4 本章小节本章介绍了 ARM程序设计的一些基本概念,以及在汇编语言程序设计中常见的伪指令、汇编语言的基本语句格式等,汇编语言程序的基本结构等,同时简单介绍了 C/C和汇编语言的混合编程等问题,这些问题均为程序设计中的基本问题,希望读者掌握,注意本章最后的两个示例均与后面章节介绍的基于 S3C4510B的硬件平台有关系,读者可以参考第五、六章的相关内容。