Date:12.Sept.2005
NEUSOFTInstituteofInformationTechnology,ChengDu
嵌入式系统原理与接口技术
第3章ARM寻址方式与指令系统
NEUSOFTInstituteofinformationTechnology.ChengDu成都东软信息技术学院计算机系杨宗德028-82878167Yangzd@
Date:12.Sept.2005
NEUSOFTInstituteofInformationTechnology,ChengDu
第4章汇编语言程序设计
汇编语言源程序格式汇编语言上机过程
汇编语言与C语言混合编程技术Linux下的ARM汇编
程序优化与性能测试
Date:12.Sept.2005
NEUSOFTInstituteofInformationTechnology,ChengDu
编程工具
•直接面向硬件的开发–SDT、ADS(集成开发环境)–CodeWorrier
•面向特定操作系统的应用–面向WinCE的EmbededVC–面向Symbian的C/C++集成开发环境–面向Linux的GNUTools(主要是GCC/G++)
•操作系统开发–GCC/C++(支持uClinux,Linux,ECOS,uC/OS-II等)
•其它–J2ME等基于JAVA的编程
Date:12.Sept.2005
编程语言
•汇编语言•C/C++语言
–C与汇编混合编程•Java语言
NEUSOFTInstituteofInformationTechnology,ChengDu
Date:12.Sept.2005
ARM源程序文件
文件类型汇编语言源文件C语言源文件C++源文件引入文件头文件
NEUSOFTInstituteofInformationTechnology,ChengDu
扩展名.s.c.cpp.INC.h
Date:12.Sept.2005
汇编源程序示例Ⅰ
NEUSOFTInstituteofInformationTechnology,ChengDu
Date:12.Sept.2005
汇编源程序示例Ⅱ
NEUSOFTInstituteofInformationTechnology,ChengDu
Date:12.Sept.2005
汇编源程序示例Ⅲ
NEUSOFTInstituteofInformationTechnology,ChengDu
Date:12.Sept.2005
汇编源程序示例Ⅳ
NEUSOFTInstituteofInformationTechnology,ChengDu
•ARM的汇编语言程序一般由几个段组成,每个段均由AREA伪操作定义。
•段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,象代码段的默认属性为READONLY,数据段的默认属性为READWRITE。
•本程序定义了两个段,第一个段为代码段codesec,它在存储器中存放用于程序执行的代码以及main函数的本地字符串;第二个段为数据段constdatasec,存放了全局的字符串,由于本程序没有对数据进行写操作,该数据段定义属性为READONLY。
Date:12.Sept.2005 汇编语言的行构成Ⅰ NEUSOFTInstituteofInformationTechnology,ChengDu 格式: •[标签]指令/伪操作/伪指令操作数[;语句的注释] ¾所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C语言中的标签一样加上“:”; ¾ARM汇编器对标识符的大小写敏感书写标号及指令时字母的大小写要一致; ¾注释使用“;”符号,注释的内容从“;”开始到该行的结尾结束。
Date:12.Sept.2005 汇编语言的行构成Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu •标签 标签是一个符号,可以代表指令的地址、变量、数据的地址和常量。
一般以字母开头,由字母、数字、下划线组成。
当符号代表地址时又称标号,可以以数字开头,其作用范围为当前段或者在下一个ROUT伪操作之前。
•指令/伪操作 指令/伪操作是指令的助记符或者定义符,它告诉ARM的处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言的标号 •标号代表地址。
标号分为段内标号和和段外标号。
段内标号的地址值在汇编时确定,段外编号的地址值在链接时确定。
•在程序段中,标号代表其所在位置与段首地址的偏移量。
根据程序计数器(PC)和偏移量计算地址即程序相对寻址。
•在映像中定义的标号代表标号到映像首地址的偏移量。
映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址即寄存器相对寻址。
•此外在宏中也可以使用局部符号。
局部标号是0~99的十进位数开始,可以重复定义。
局部标号引用格式:%{F|B}{A|T}N{routname} Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言的常量 程序中的常量是指其值在程序的运行过程中不能被改变的量。
¾数字常量:数字常量有3种表示方式:•十进制数,如1、2、123•十六进制数,如0x123,0xabc•n进制数,形式为n_XXX,n的范围是2到
9,XXX是具体数字¾字符常量:由单引号及中间的字符组成,包括C语言中的转义字符, 如’a’,’\n’¾字符串常量:由一对双引号及中间的字符串表示,中间也可以使用C语 言中的转义字符,比如:“abcdef\0xa\r\n”¾逻辑常量:{TRUE},{FALSE},注意带大括号 Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的变量代换Ⅰ 这里所说的变量,是相对于汇编程序的“变量”,是用于汇编程序进行处理的,但一旦编译到程序中,则不会改变,成为常量。
¾如果在字符串变量的前面有一个$字符,在汇编时编译器将用该字符串变量的内容代替该串变量。
¾如果在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并用该十六进制的字符串代换“$”后的数字变量。
¾如果需要将“$”字符加入到字符串中,可以用“$$”代替,此时编译器将不再进行变量代换,而是把“$$”看作一个“$”. ¾一般的,在两个“|”之间的“$”并不进行变量的代换,但如果“|”在双引号内,则将进行变量代换。
¾使用“.”来表示字符串中变量名的结束。
Date:12.Sept.2005 汇编程序的变量代换Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 伪指令 •在ARM汇编语言源程序中有些特殊助记符,它们没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。
伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。
¾符号定义伪指令¾数据定义伪指令¾汇编控制伪指令¾信息报告伪指令¾宏指令以及其他伪指令。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 符号定义伪指令 •LCLA(localArithmetic)局部数字变量,初始化为0•LCLL(localLogic)局部逻辑变量,初始化为F•LCAS(LocalString)局部字符串变量,初始化为空•GBLA(globalArithmetic)全局数字变量,初始化为0•GBLL(GlobalLogic)全局逻辑变量,初始化为F•GBLS(GlobalString)全局字符串变量,初始化为空•SETA(setArithmetic)给数字变量赋值•SETL(setLogic)给逻辑变量赋值•SETS(setstring)给字符串变量赋值•RLIST(Registerlistset)寄存器列表别名 Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 数据定义伪指令 •DCB(DistributecontinueBit)一个字节“=”•DCW/DCWU(Distributecontinueword)两个字节•DCD/DCDU(DistributecontinueDouble)四个字节“&”•DCQ/DCQU(DistributecontinueQuadplex)八个字节•DCFS/DCFSU(Distributecontinuefloatsingle)•DCFD/DCFDU(Distributecontinuefloatdouble)•SPACE(一块连续的存储单元)“%”•FIELD(定义一个结构化的内存表的数据域)“#”•MAP(一个结构化的内存表首地直址)“^” Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编控制伪指令 •MACRO\MENDandMEXIT宏•IF_ELSE_ENDIF可用[|]代替•WHILEandWEND Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu Others •ASSERT:表示程序编译必须满足一定的条件,如果表达式不满足,则报错。
ASSERTver>
7 •AREA:AREA定义代码段、数据段或者特定的属性。
–DATA/CODE/READONLY/READWRITE/ALIGN/COMMON •CODE32/CODE16 •ENTRY •END •EQU•EXPORT(声明全局标号)/GLOBAL•IMPORT•EXTERN(告诉编译器所使用的标号要在当前源文件中引用,但如果没 有用到也不报错)•GET/INCLUDE•INCBIN(二进制的)•RN(寄存器取别名)•ROUT(给全局变量定义作用范围) Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言上机过程 用ARM汇编语言编写的源程序,要使之运行必须经过以下几个步骤:¾
1.编辑汇编源程序,保存为文件名后缀是“.s”的文件;¾
2.调用汇编程序对源程序进行汇编,生成目标文件;¾
3.连接目标文件,生成可以放进ARM软件仿真器进行调试的映象文件或者可下载到ARM的目标板执行的二进制文件;¾
4.对生成的最终文件进行调试。
Date:12.Sept.2005 ARM的开发工具ADS1.2 NEUSOFTInstituteofInformationTechnology,ChengDu ADS1.2是ARM公司推出的一套ARM汇编、
C、C++的集成开发环境。
包含了几个有用的开发工具,包括: ¾CodeWarriorIDEfortheARMDeveloperSuite:为ARM的程序员管理、开发软件工程项目提供了一个简单直观、灵活的用户界面。
¾AXDDebuger:AXD是一个功能强大、使用方便的调试器。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编辑汇编语言源程序 •可以使用简单的Windows自带的记事本程序来编辑ARM的汇编程序:单击开始菜单Æ程序Æ附件Æ记事本Æ敲入汇编代码Æ保存为.s文件 •也可以使用CodeWarriorIDE来编辑汇编程序:单击File菜单的New菜单项Æ单击Project标签页 Æ单击工具栏的NewText按钮Æ敲入汇编代码Æ保存为hello.s文件Æ单击Project菜单,选择“Add*.stoproject” Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅰ •ARM的编译器有如下几种¾:ARMC编译器,具有优化功能,兼容ANSIC¾:Thumb的C编译器,同样具有优化功能兼容ANSIC。
¾armcpp:ARMC++编译器,遵循ANSIC++或者EC++标准¾tcpp:Thubm的C++编译器,遵循ANSIC++或者EC++标准¾armasm:支持ARM和Thumb的汇编器 这些编译器输出的是ELF格式的目标文件,可以包括RAWF2格式的调试信息。
同时通过特殊的控制选项可以输出汇编语言文件或者列表文件。
Date:12.Sept.2005 编译汇编语言源程序Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu •4种ARMC和C++编译器(,,armcpp和tcpp)的命令通用语法: compiler[PCS-options][source-language][search-paths][preprocessor-options][output-format][target-options] [debug-options][code-generation-options][warning-options][additional-checks][error-options][source][-viafilename] 用户通过命令行操作选项指引编译器运行。
所有的选项都是以符号”-”开始,有些选项后面还跟有参数。
在大多数情况下,ARMC和C++编译器允许在选项和参数之间存在空格。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅲ ¾PCS-options:指定了要使用的过程调用标准;¾source-language:指定了编译器可以接受的编写源程序的语言种类。
对 于C编译器默认的语言是ANSIC,对于C++编译器默认是ISO标准C++;¾search-paths:该选项指定了对包含的文件(包括源文件和头文件)的搜 索路径;¾preprocessor-options:该选项指定了预处理器的行为,其中包括预处 理器的输出和宏定义等特性;¾output-format:该选项指定了编译器的输出格式,可以使用该项生成汇 编语言输出列表文件和目标文件;¾target-options:该选项指定目标处理器或ARM体系结构;¾debug-options:该选项指定调试信息表是否生成,和该调试信息表生成 时的格式; Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅳ ¾code-generation-options:该选项指定了例如优化,字节顺序和由编译器产生的数据对齐格式等选项; ¾warning-options:该选项决定警告信息是否产生;¾additional-checks:该选项指定了几个能用于源码的附加检查,例如检 查数据流异常,检查没有使用的声明等;¾error-options:该选项可以关闭指定的可恢复的错误,或者将一些指定 的错误降级为警告;¾source:该选项提供了包含有C或C++源代码的一个或多个文件名,默认 的,编译器在当前路径寻找源文件和创建输出文件。
如果源文件是用汇编语言编写的(也就是说该文件的文件名是以.s作为扩展名),汇编器将被调用来处理这些源文件。
¾-viafilename:WINDOWS系统对命令行的长度有限制,可以通过filename的文件读取命令行选项。
用户可以对-via进行嵌套调用,在文件filename中再通过-viafilename2包含了另外一个文件。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 连接装配汇编程序Ⅰ •使用armlink程序对ARM的汇编源程序进行连接,它也可以将多个.o目标文件连接生成最终的可执行文件。
•术语:¾映像文件(image):是指一个可执行文件,在执行的时候被 加载到处理器中。
一个映像文件可以有多个线程。
它是ELF(Executableandlinkingformat)格式的。
¾段(Section):描述映像文件的代码或数据块。
¾RO:Read-only缩写。
¾RW:是Read-write缩写。
¾ZI:是Zero-initialized缩写。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 连接装配汇编程序Ⅱ ¾ReadOnlyPositionIndependent(ROPI):只读数据中代码和的地址在运行时候可以改变。
¾ReadWritePositionIndependent(RWPI):一个段中的可读/写的数据地址在运行期间可以改变。
¾输入段(inputsection):它包含着代码,初始化数据或描述了在应用程序运行之前必须要初始化为0的一段内存。
¾输出段(outputsection):它包含了一系列具有相同的RO,RW或ZI属性的输入段。
¾域(Regions):在一个映像文件中,一个域包含了1至3个输出段。
多个域组织在一起,就构成了最终的映像文件。
¾加载时地址:映像文件载入存储器时的地址。
¾运行时地址:映像文件运行时的地址。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的运行 生成的*.axf文件是ARM的ELF格式的可执行映像文件;这个文件可以载入AXD进行仿真调试。
使用armsd在终端模拟它在ARM目标机上的运行: ¾执行armsd-exec*.axf¾直接在CodeWarriorIDE中运行映象文件:在project窗口中点击run按钮。
在AXD上调试成功之后,我们可以通过fromelf工具将ELF文件转换为二进制格式文件下载到目标板执行。
转化的命令如下: fromelf*.axf-bin* Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的调试 •使用AXD进行调试:编译、连接成功之后,我们可以点击project窗口的debug按钮启动AXD进行调试: 主框架窗口上方的调试工具栏有几个常用的按钮:¾go:使程序运行直到下一个断点停止¾stepin:进入函数内部运行¾step:单步调试,每次移动一行¾stepout:跳出循环或函数¾runtocursor:运行到光标所在的位置然后停止。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言与C语言混合编程技术 •ARM体系结构支持ARM的汇编语言与C与C++的混合编程.一 般的在一个完整的程序设计的中,除了初始化部分用汇编语言完成外,其大部分的编程任务一般都用C或C++完 成。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序中访问C程序变量Ⅰ 在汇编的源程序中调用C语言风格的字符串需要使用IMPORT伪操作。
IMPORT相当于C语言中的extern关键字,告诉编译器引用的符号不是在本文件中定义的,而是在其他的源文件中定义的。
IMPORTsymbol[,WEAK] symbol是声明的符号的名称;[,WEAK]指示编译器如果发现symbol在所有的源文件中都没有找到,那么它也不会产生任何的错误信息。
示例见下页。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序中 C语言代码文件str.c,里面只有一个简单的字符串的定义 char*strhello="Helloworld!
\n\0"; 汇编代码文件hello.s
1 AREA||.text||,CODE,READONLY 2mainPROC
3 STMFD sp!
,{lr}
4 LDR r0,strtemp
5 LDR r0,[r0]
6 BL _printf
7 LDMFD sp!
,{pc} 访 8
strtemp
9 DCD strhello 10 ENDP 问11 EXPORTmain 12 IMPORTstrhello C13 IMPORT_main 程 14 IMPORT__main 15 IMPORT_printf 序 16 IMPORT||Lib$$Request$$armlib||,WEAK 17 END 变 量 Date:12.Sept.2005 C程序中内嵌汇编指令Ⅰ NEUSOFTInstituteofInformationTechnology,ChengDu •在ARM的C语言程序中我们可以使用关键字__asm来加入一段汇编语言的程序,格式如下: __asm{ instruction/ment*/…} Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C程序中内嵌汇编指令Ⅱ •在C语言中嵌入的ARM汇编需要注意一些问题: ¾在汇编指令中,可以使用表达式,使用逗号“,”作为分隔符; ¾如果一条指令占用了多行,那么应该使用符号“\”续行,如果一行中有多个汇编指令,那么应该使用“;”将多个指令隔开,汇编中不能再使用“;”作为注释行的开头,而应该使用C语言中的“/**/”或者“//”进行注释; ¾不要企图使用一个物理寄存器去改变一个C变量; ¾对于内嵌的汇编代码用到的寄存器,编译器在编译时会自动加入保存和恢复这些寄存器的代码而不用用户去管理,除了寄存器CPSR和SPSR,其他寄存器都必须先赋值然后再读取,否则编译时将出现错误。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C程序中内嵌汇编指令Ⅲ •内嵌的ARM汇编与纯粹的ARM汇编的区别有:¾内嵌的ARM汇编不支持ADR、ADRL伪指令;¾十六进制数使用0x作为前缀,而后者使用&;¾编译器在编译函数时使用R0、R1、R2、R3、IP和LR存放中间结果,因此使用这些寄存器时要特别小心;¾注意C语言中的C语言变量不要和物理寄存器同名,否则可能出现混乱;¾内嵌的汇编代码不能使用PC寄存器返回当前指令的地址;¾STM和LDM指令中不能使用C语言表达式;¾不支持BX和BLX;¾用户可以改变处理器的模式,但仍然需要自己把处理器模式恢复过来,编译器不会自动做处理;¾嵌汇编指令常量前面的符号“#”可以省略;¾嵌汇编指令不支持内存分配的伪操作。
Date:12.Sept.2005 C程序调用汇编程序 NEUSOFTInstituteofInformationTechnology,ChengDu •为了满足ARM汇编、C与C++之间的互相调用,必须保证编写的代码遵循APCS(ARM过程调用标准)。
APCS规定了子程序调用 的基本规则,这些规则包括子程序调用过程中寄存器、数据栈 的使用规则以及参数的传递规则。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(1) •C/ASM相互调用基于ATPCS(ARM/ThumbProcdureCallStandard),也可简称APCS •C中内嵌汇编 基于ADS __asm {指令[;指令]/*注释*/…..[指令] } 基于GNUC __asm____volatile__(“指令@注释…..[指令] :属性设置1:属性设置2) Asm(“指令”:属性1:属性2) Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(2) •内嵌汇编的语法 –操作数:作为操作数的寄存器和产量可以是char\short\int型的C表达式。
–物理寄存器:不要使用复杂的C表达式;一般不要使用R0~R3,R12(IP),R14(LR) –不要使用寄存器代替变量 Date:12.Sept.2005 C与汇编混合编程
(3) NEUSOFTInstituteofInformationTechnology,ChengDu •交互规则:–寄存器规则:v1-v8(R4-R11)用来保存局部变量–堆栈规则:FD类型(满递减)堆栈–参数传递规则:如果参数个数小于等于
4,用R0-R3保存参数;参数个数多于4的情况下,剩余的参数传入堆栈–子程序结果返回规则:•结果为一个32位整数,通过R0返回;•结果为一个64位整数,通过R0、R1返回;•对于位数更多的结果,通过内存传递。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(4) •C调用汇编 C代码…externvoidscopy(char*d,char*s);…scopy(dststr,srcstr 汇编代码AREAexample,CODE,READONLYEXPORTscopyscopy LDRBR2,[R1],#1STRBR2,[R1],#1CMPR2,#0BNEscopyMOVpc,lrEND Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(5) •汇编调用
C 汇编代码 EXPORTcallsum5 AREAexample,CODE,READONLY IMPORTsum5 callsum5 STMFDSP!
,{LR} ;LR入栈 ADDR1,R0,R0 ;R0=a,R1=b,R2=c ADDR2,R1,R0 ADDR3,R1,R2 STRR3,[SP,#-4]!
;einstack ADDR3,R1,R1 ;R3=d BLsum5 ;callR5,R0=result ADDSP,SP,#
4 LDMFDSP!
,{PC} END C代码Intsum5(inta,intb,intc,intd,inte){return(a+b+c+d+e);}
•段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,象代码段的默认属性为READONLY,数据段的默认属性为READWRITE。
•本程序定义了两个段,第一个段为代码段codesec,它在存储器中存放用于程序执行的代码以及main函数的本地字符串;第二个段为数据段constdatasec,存放了全局的字符串,由于本程序没有对数据进行写操作,该数据段定义属性为READONLY。
Date:12.Sept.2005 汇编语言的行构成Ⅰ NEUSOFTInstituteofInformationTechnology,ChengDu 格式: •[标签]指令/伪操作/伪指令操作数[;语句的注释] ¾所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟C语言中的标签一样加上“:”; ¾ARM汇编器对标识符的大小写敏感书写标号及指令时字母的大小写要一致; ¾注释使用“;”符号,注释的内容从“;”开始到该行的结尾结束。
Date:12.Sept.2005 汇编语言的行构成Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu •标签 标签是一个符号,可以代表指令的地址、变量、数据的地址和常量。
一般以字母开头,由字母、数字、下划线组成。
当符号代表地址时又称标号,可以以数字开头,其作用范围为当前段或者在下一个ROUT伪操作之前。
•指令/伪操作 指令/伪操作是指令的助记符或者定义符,它告诉ARM的处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言的标号 •标号代表地址。
标号分为段内标号和和段外标号。
段内标号的地址值在汇编时确定,段外编号的地址值在链接时确定。
•在程序段中,标号代表其所在位置与段首地址的偏移量。
根据程序计数器(PC)和偏移量计算地址即程序相对寻址。
•在映像中定义的标号代表标号到映像首地址的偏移量。
映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址即寄存器相对寻址。
•此外在宏中也可以使用局部符号。
局部标号是0~99的十进位数开始,可以重复定义。
局部标号引用格式:%{F|B}{A|T}N{routname} Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言的常量 程序中的常量是指其值在程序的运行过程中不能被改变的量。
¾数字常量:数字常量有3种表示方式:•十进制数,如1、2、123•十六进制数,如0x123,0xabc•n进制数,形式为n_XXX,n的范围是2到
9,XXX是具体数字¾字符常量:由单引号及中间的字符组成,包括C语言中的转义字符, 如’a’,’\n’¾字符串常量:由一对双引号及中间的字符串表示,中间也可以使用C语 言中的转义字符,比如:“abcdef\0xa\r\n”¾逻辑常量:{TRUE},{FALSE},注意带大括号 Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的变量代换Ⅰ 这里所说的变量,是相对于汇编程序的“变量”,是用于汇编程序进行处理的,但一旦编译到程序中,则不会改变,成为常量。
¾如果在字符串变量的前面有一个$字符,在汇编时编译器将用该字符串变量的内容代替该串变量。
¾如果在数字变量前面有一个代换操作符“$”,编译器会将该数字变量的值转换为十六进制的字符串,并用该十六进制的字符串代换“$”后的数字变量。
¾如果需要将“$”字符加入到字符串中,可以用“$$”代替,此时编译器将不再进行变量代换,而是把“$$”看作一个“$”. ¾一般的,在两个“|”之间的“$”并不进行变量的代换,但如果“|”在双引号内,则将进行变量代换。
¾使用“.”来表示字符串中变量名的结束。
Date:12.Sept.2005 汇编程序的变量代换Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 伪指令 •在ARM汇编语言源程序中有些特殊助记符,它们没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。
伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。
¾符号定义伪指令¾数据定义伪指令¾汇编控制伪指令¾信息报告伪指令¾宏指令以及其他伪指令。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 符号定义伪指令 •LCLA(localArithmetic)局部数字变量,初始化为0•LCLL(localLogic)局部逻辑变量,初始化为F•LCAS(LocalString)局部字符串变量,初始化为空•GBLA(globalArithmetic)全局数字变量,初始化为0•GBLL(GlobalLogic)全局逻辑变量,初始化为F•GBLS(GlobalString)全局字符串变量,初始化为空•SETA(setArithmetic)给数字变量赋值•SETL(setLogic)给逻辑变量赋值•SETS(setstring)给字符串变量赋值•RLIST(Registerlistset)寄存器列表别名 Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 数据定义伪指令 •DCB(DistributecontinueBit)一个字节“=”•DCW/DCWU(Distributecontinueword)两个字节•DCD/DCDU(DistributecontinueDouble)四个字节“&”•DCQ/DCQU(DistributecontinueQuadplex)八个字节•DCFS/DCFSU(Distributecontinuefloatsingle)•DCFD/DCFDU(Distributecontinuefloatdouble)•SPACE(一块连续的存储单元)“%”•FIELD(定义一个结构化的内存表的数据域)“#”•MAP(一个结构化的内存表首地直址)“^” Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编控制伪指令 •MACRO\MENDandMEXIT宏•IF_ELSE_ENDIF可用[|]代替•WHILEandWEND Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu Others •ASSERT:表示程序编译必须满足一定的条件,如果表达式不满足,则报错。
ASSERTver>
7 •AREA:AREA定义代码段、数据段或者特定的属性。
–DATA/CODE/READONLY/READWRITE/ALIGN/COMMON •CODE32/CODE16 •ENTRY •END •EQU•EXPORT(声明全局标号)/GLOBAL•IMPORT•EXTERN(告诉编译器所使用的标号要在当前源文件中引用,但如果没 有用到也不报错)•GET/INCLUDE•INCBIN(二进制的)•RN(寄存器取别名)•ROUT(给全局变量定义作用范围) Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言上机过程 用ARM汇编语言编写的源程序,要使之运行必须经过以下几个步骤:¾
1.编辑汇编源程序,保存为文件名后缀是“.s”的文件;¾
2.调用汇编程序对源程序进行汇编,生成目标文件;¾
3.连接目标文件,生成可以放进ARM软件仿真器进行调试的映象文件或者可下载到ARM的目标板执行的二进制文件;¾
4.对生成的最终文件进行调试。
Date:12.Sept.2005 ARM的开发工具ADS1.2 NEUSOFTInstituteofInformationTechnology,ChengDu ADS1.2是ARM公司推出的一套ARM汇编、
C、C++的集成开发环境。
包含了几个有用的开发工具,包括: ¾CodeWarriorIDEfortheARMDeveloperSuite:为ARM的程序员管理、开发软件工程项目提供了一个简单直观、灵活的用户界面。
¾AXDDebuger:AXD是一个功能强大、使用方便的调试器。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编辑汇编语言源程序 •可以使用简单的Windows自带的记事本程序来编辑ARM的汇编程序:单击开始菜单Æ程序Æ附件Æ记事本Æ敲入汇编代码Æ保存为.s文件 •也可以使用CodeWarriorIDE来编辑汇编程序:单击File菜单的New菜单项Æ单击Project标签页 Æ单击工具栏的NewText按钮Æ敲入汇编代码Æ保存为hello.s文件Æ单击Project菜单,选择“Add*.stoproject” Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅰ •ARM的编译器有如下几种¾:ARMC编译器,具有优化功能,兼容ANSIC¾:Thumb的C编译器,同样具有优化功能兼容ANSIC。
¾armcpp:ARMC++编译器,遵循ANSIC++或者EC++标准¾tcpp:Thubm的C++编译器,遵循ANSIC++或者EC++标准¾armasm:支持ARM和Thumb的汇编器 这些编译器输出的是ELF格式的目标文件,可以包括RAWF2格式的调试信息。
同时通过特殊的控制选项可以输出汇编语言文件或者列表文件。
Date:12.Sept.2005 编译汇编语言源程序Ⅱ NEUSOFTInstituteofInformationTechnology,ChengDu •4种ARMC和C++编译器(,,armcpp和tcpp)的命令通用语法: compiler[PCS-options][source-language][search-paths][preprocessor-options][output-format][target-options] [debug-options][code-generation-options][warning-options][additional-checks][error-options][source][-viafilename] 用户通过命令行操作选项指引编译器运行。
所有的选项都是以符号”-”开始,有些选项后面还跟有参数。
在大多数情况下,ARMC和C++编译器允许在选项和参数之间存在空格。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅲ ¾PCS-options:指定了要使用的过程调用标准;¾source-language:指定了编译器可以接受的编写源程序的语言种类。
对 于C编译器默认的语言是ANSIC,对于C++编译器默认是ISO标准C++;¾search-paths:该选项指定了对包含的文件(包括源文件和头文件)的搜 索路径;¾preprocessor-options:该选项指定了预处理器的行为,其中包括预处 理器的输出和宏定义等特性;¾output-format:该选项指定了编译器的输出格式,可以使用该项生成汇 编语言输出列表文件和目标文件;¾target-options:该选项指定目标处理器或ARM体系结构;¾debug-options:该选项指定调试信息表是否生成,和该调试信息表生成 时的格式; Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 编译汇编语言源程序Ⅳ ¾code-generation-options:该选项指定了例如优化,字节顺序和由编译器产生的数据对齐格式等选项; ¾warning-options:该选项决定警告信息是否产生;¾additional-checks:该选项指定了几个能用于源码的附加检查,例如检 查数据流异常,检查没有使用的声明等;¾error-options:该选项可以关闭指定的可恢复的错误,或者将一些指定 的错误降级为警告;¾source:该选项提供了包含有C或C++源代码的一个或多个文件名,默认 的,编译器在当前路径寻找源文件和创建输出文件。
如果源文件是用汇编语言编写的(也就是说该文件的文件名是以.s作为扩展名),汇编器将被调用来处理这些源文件。
¾-viafilename:WINDOWS系统对命令行的长度有限制,可以通过filename的文件读取命令行选项。
用户可以对-via进行嵌套调用,在文件filename中再通过-viafilename2包含了另外一个文件。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 连接装配汇编程序Ⅰ •使用armlink程序对ARM的汇编源程序进行连接,它也可以将多个.o目标文件连接生成最终的可执行文件。
•术语:¾映像文件(image):是指一个可执行文件,在执行的时候被 加载到处理器中。
一个映像文件可以有多个线程。
它是ELF(Executableandlinkingformat)格式的。
¾段(Section):描述映像文件的代码或数据块。
¾RO:Read-only缩写。
¾RW:是Read-write缩写。
¾ZI:是Zero-initialized缩写。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 连接装配汇编程序Ⅱ ¾ReadOnlyPositionIndependent(ROPI):只读数据中代码和的地址在运行时候可以改变。
¾ReadWritePositionIndependent(RWPI):一个段中的可读/写的数据地址在运行期间可以改变。
¾输入段(inputsection):它包含着代码,初始化数据或描述了在应用程序运行之前必须要初始化为0的一段内存。
¾输出段(outputsection):它包含了一系列具有相同的RO,RW或ZI属性的输入段。
¾域(Regions):在一个映像文件中,一个域包含了1至3个输出段。
多个域组织在一起,就构成了最终的映像文件。
¾加载时地址:映像文件载入存储器时的地址。
¾运行时地址:映像文件运行时的地址。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的运行 生成的*.axf文件是ARM的ELF格式的可执行映像文件;这个文件可以载入AXD进行仿真调试。
使用armsd在终端模拟它在ARM目标机上的运行: ¾执行armsd-exec*.axf¾直接在CodeWarriorIDE中运行映象文件:在project窗口中点击run按钮。
在AXD上调试成功之后,我们可以通过fromelf工具将ELF文件转换为二进制格式文件下载到目标板执行。
转化的命令如下: fromelf*.axf-bin* Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序的调试 •使用AXD进行调试:编译、连接成功之后,我们可以点击project窗口的debug按钮启动AXD进行调试: 主框架窗口上方的调试工具栏有几个常用的按钮:¾go:使程序运行直到下一个断点停止¾stepin:进入函数内部运行¾step:单步调试,每次移动一行¾stepout:跳出循环或函数¾runtocursor:运行到光标所在的位置然后停止。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编语言与C语言混合编程技术 •ARM体系结构支持ARM的汇编语言与C与C++的混合编程.一 般的在一个完整的程序设计的中,除了初始化部分用汇编语言完成外,其大部分的编程任务一般都用C或C++完 成。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序中访问C程序变量Ⅰ 在汇编的源程序中调用C语言风格的字符串需要使用IMPORT伪操作。
IMPORT相当于C语言中的extern关键字,告诉编译器引用的符号不是在本文件中定义的,而是在其他的源文件中定义的。
IMPORTsymbol[,WEAK] symbol是声明的符号的名称;[,WEAK]指示编译器如果发现symbol在所有的源文件中都没有找到,那么它也不会产生任何的错误信息。
示例见下页。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu 汇编程序中 C语言代码文件str.c,里面只有一个简单的字符串的定义 char*strhello="Helloworld!
\n\0"; 汇编代码文件hello.s
1 AREA||.text||,CODE,READONLY 2mainPROC
3 STMFD sp!
,{lr}
4 LDR r0,strtemp
5 LDR r0,[r0]
6 BL _printf
7 LDMFD sp!
,{pc} 访 8
strtemp
9 DCD strhello 10 ENDP 问11 EXPORTmain 12 IMPORTstrhello C13 IMPORT_main 程 14 IMPORT__main 15 IMPORT_printf 序 16 IMPORT||Lib$$Request$$armlib||,WEAK 17 END 变 量 Date:12.Sept.2005 C程序中内嵌汇编指令Ⅰ NEUSOFTInstituteofInformationTechnology,ChengDu •在ARM的C语言程序中我们可以使用关键字__asm来加入一段汇编语言的程序,格式如下: __asm{ instruction/ment*/…} Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C程序中内嵌汇编指令Ⅱ •在C语言中嵌入的ARM汇编需要注意一些问题: ¾在汇编指令中,可以使用表达式,使用逗号“,”作为分隔符; ¾如果一条指令占用了多行,那么应该使用符号“\”续行,如果一行中有多个汇编指令,那么应该使用“;”将多个指令隔开,汇编中不能再使用“;”作为注释行的开头,而应该使用C语言中的“/**/”或者“//”进行注释; ¾不要企图使用一个物理寄存器去改变一个C变量; ¾对于内嵌的汇编代码用到的寄存器,编译器在编译时会自动加入保存和恢复这些寄存器的代码而不用用户去管理,除了寄存器CPSR和SPSR,其他寄存器都必须先赋值然后再读取,否则编译时将出现错误。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C程序中内嵌汇编指令Ⅲ •内嵌的ARM汇编与纯粹的ARM汇编的区别有:¾内嵌的ARM汇编不支持ADR、ADRL伪指令;¾十六进制数使用0x作为前缀,而后者使用&;¾编译器在编译函数时使用R0、R1、R2、R3、IP和LR存放中间结果,因此使用这些寄存器时要特别小心;¾注意C语言中的C语言变量不要和物理寄存器同名,否则可能出现混乱;¾内嵌的汇编代码不能使用PC寄存器返回当前指令的地址;¾STM和LDM指令中不能使用C语言表达式;¾不支持BX和BLX;¾用户可以改变处理器的模式,但仍然需要自己把处理器模式恢复过来,编译器不会自动做处理;¾嵌汇编指令常量前面的符号“#”可以省略;¾嵌汇编指令不支持内存分配的伪操作。
Date:12.Sept.2005 C程序调用汇编程序 NEUSOFTInstituteofInformationTechnology,ChengDu •为了满足ARM汇编、C与C++之间的互相调用,必须保证编写的代码遵循APCS(ARM过程调用标准)。
APCS规定了子程序调用 的基本规则,这些规则包括子程序调用过程中寄存器、数据栈 的使用规则以及参数的传递规则。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(1) •C/ASM相互调用基于ATPCS(ARM/ThumbProcdureCallStandard),也可简称APCS •C中内嵌汇编 基于ADS __asm {指令[;指令]/*注释*/…..[指令] } 基于GNUC __asm____volatile__(“指令@注释…..[指令] :属性设置1:属性设置2) Asm(“指令”:属性1:属性2) Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(2) •内嵌汇编的语法 –操作数:作为操作数的寄存器和产量可以是char\short\int型的C表达式。
–物理寄存器:不要使用复杂的C表达式;一般不要使用R0~R3,R12(IP),R14(LR) –不要使用寄存器代替变量 Date:12.Sept.2005 C与汇编混合编程
(3) NEUSOFTInstituteofInformationTechnology,ChengDu •交互规则:–寄存器规则:v1-v8(R4-R11)用来保存局部变量–堆栈规则:FD类型(满递减)堆栈–参数传递规则:如果参数个数小于等于
4,用R0-R3保存参数;参数个数多于4的情况下,剩余的参数传入堆栈–子程序结果返回规则:•结果为一个32位整数,通过R0返回;•结果为一个64位整数,通过R0、R1返回;•对于位数更多的结果,通过内存传递。
Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(4) •C调用汇编 C代码…externvoidscopy(char*d,char*s);…scopy(dststr,srcstr 汇编代码AREAexample,CODE,READONLYEXPORTscopyscopy LDRBR2,[R1],#1STRBR2,[R1],#1CMPR2,#0BNEscopyMOVpc,lrEND Date:12.Sept.2005 NEUSOFTInstituteofInformationTechnology,ChengDu C与汇编混合编程
(5) •汇编调用
C 汇编代码 EXPORTcallsum5 AREAexample,CODE,READONLY IMPORTsum5 callsum5 STMFDSP!
,{LR} ;LR入栈 ADDR1,R0,R0 ;R0=a,R1=b,R2=c ADDR2,R1,R0 ADDR3,R1,R2 STRR3,[SP,#-4]!
;einstack ADDR3,R1,R1 ;R3=d BLsum5 ;callR5,R0=result ADDSP,SP,#
4 LDMFDSP!
,{PC} END C代码Intsum5(inta,intb,intc,intd,inte){return(a+b+c+d+e);}
声明:
该资讯来自于互联网网友发布,如有侵犯您的权益请联系我们。
下一篇入门指南,cat怎么读