第4章 汇编语言程序设计

47
第4第 第第第第第第第第 第第第第 第第第

Upload: jonah-saunders

Post on 30-Dec-2015

75 views

Category:

Documents


0 download

DESCRIPTION

第4章 汇编语言程序设计. 主讲教师:罗白云. 本章主要内容 汇编语言源程序格式 汇编语言上机过程 汇编语言与 C 语言混合编程技术 Linux 下的 ARM 汇编 程序优化与性能测试. 文件类型. 扩展名. 汇编语言源文件. . s. C 语言源文件. . c. C++ 源文件. . cpp. 引入文件. . INC. 头文件. . h. 4.1 ARM 源程序文件. 汇编源程序示例Ⅰ. 汇编源程序示例 Ⅱ. 汇编源程序示例 Ⅲ. 汇编源程序示例Ⅳ. ARM 的汇编语言程序一般由几个段组成,每个段均由 AREA 伪操作定义。 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第4章 汇编语言程序设计

第 4 章 汇编语言程序设计

主讲教师:罗白云

Page 2: 第4章 汇编语言程序设计

2

本章主要内容

汇编语言源程序格式 汇编语言上机过程 汇编语言与 C 语言混合编程技术 Linux 下的 ARM 汇编 程序优化与性能测试

Page 3: 第4章 汇编语言程序设计

4.1   ARM 源程序文件 4.1   ARM 源程序文件

文件类型 扩展名

汇编语言源文件 .s

C语言源文件 .c

C++源文件 .cpp

引入文件 .INC

头文件 .h

Page 4: 第4章 汇编语言程序设计

汇编源程序示例Ⅰ  汇编源程序示例Ⅰ 

Page 5: 第4章 汇编语言程序设计

汇编源程序示例Ⅱ汇编源程序示例Ⅱ

Page 6: 第4章 汇编语言程序设计

汇编源程序示例Ⅲ汇编源程序示例Ⅲ

Page 7: 第4章 汇编语言程序设计

汇编源程序示例Ⅳ汇编源程序示例Ⅳ

ARM 的汇编语言程序一般由几个段组成,每个段均由AREA 伪操作定义。

段可以分为多种,如代码段、数据段、通用段,每个段又有不同的属性,象代码段的默认属性为 READONLY ,数据段的默认属性为 READWRITE 。

本程序定义了两个段,第一个段为代码段 codesec ,它在存储器中存放用于程序执行的代码以及 main 函数的本地字符串;第二个段为数据段 constdatasec ,存放了全局的字符串,由于本程序没有对数据进行写操作,该数据段定义属性为 READONLY 。

Page 8: 第4章 汇编语言程序设计

汇编语言的行构成Ⅰ汇编语言的行构成Ⅰ

格式: [ 标签 ] 指令 / 伪操作 / 伪指令 操作数 [; 语句的注释 ]

所有的标签必须在一行的开头顶格写,前面不能留空格,后面也不能跟 C 语言中的标签一样加上“ :” ;

ARM 汇编器对标识符的大小写敏感书写标号及指令时字母的大小写要一致;

注释使用“ ;” 符号,注释的内容从“ ;” 开始到该行的结尾结束。

Page 9: 第4章 汇编语言程序设计

汇编语言的行构成Ⅱ汇编语言的行构成Ⅱ

标签 标签是一个符号,可以代表指令的地址、变量、数据的地

址和常量。一般以字母开头,由字母、数字、下划线组成。当符号代表地址时又称标号,可以以数字开头,其作用范围为当前段或者在下一个 ROUT 伪操作之前。

指令 / 伪操作 指令 / 伪操作是指令的助记符或者定义符,它告诉 ARM 的

处理器应该执行什么样的操作或者告诉汇编程序伪指令语句的伪操作功能。

Page 10: 第4章 汇编语言程序设计

汇编语言的标号汇编语言的标号

标号代表地址。标号分为段内标号和和段外标号。段内标号的地址值在汇编时确定,段外编号的地址值在链接时确定 。

在程序段中,标号代表其所在位置与段首地址的偏移量。根据程序计数器( PC )和偏移量计算地址即程序相对寻址。

在映像中定义的标号代表标号到映像首地址的偏移量。映像的首地址通常被赋予一个寄存器,根据该寄存器值与偏移量计算地址即寄存器相对寻址。

此外在宏中也可以使用局部符号。局部标号是 0~99 的十进位数开始,可以重复定义。

局部标号引用格式: % {F|B}{A|T} N{routname}

Page 11: 第4章 汇编语言程序设计

汇编语言的常量汇编语言的常量

程序中的常量是指其值在程序的运行过程中不能被改变的量。 数字常量:数字常量有 3 种表示方式:• 十进制数,如 1 、 2 、 123• 十六进制数,如 0x123,0xabc• n 进制数,形式为 n_XXX,n 的范围是 2 到 9 , XXX 是具体数字 字符常量:由单引号及中间的字符组成,包括 C 语言中的转义字

符,如’ a’,’\n’ 字符串常量:由一对双引号及中间的字符串表示,中间也可以使

用 C 语言中的转义字符,比如:“ abcdef\0xa\r\n” 逻辑常量: {TRUE},{FALSE}, 注意带大括号

Page 12: 第4章 汇编语言程序设计

汇编程序的变量代换Ⅰ汇编程序的变量代换Ⅰ

这里所说的变量,是相对于汇编程序的“变量”,是用于汇编程序进行处理的,但一旦编译到程序中,则不会改变,成为常量。

如果在字符串变量的前面有一个 $ 字符,在汇编时编译器将用该字符串变量的内容代替该串变量。

如果在数字变量前面有一个代换操作符“ $” ,编译器会将该数字变量的值转换为十六进制的字符串,并用该十六进制的字符串代换“ $” 后的数字变量。

如果需要将“ $” 字符 加入到字符串中,可以用“ $$” 代替,此时编译器将不再进行变量代换,而是把“ $$” 看作一个“ $”.

一般的,在两个“ |” 之间的“ $” 并不进行变量的代换,但如果“ |” 在双引号内,则将进行变量代换。

使用“ .” 来表示字符串中变量名的结束。

Page 13: 第4章 汇编语言程序设计

汇编程序的变量代换Ⅱ汇编程序的变量代换Ⅱ

Page 14: 第4章 汇编语言程序设计

伪指令伪指令

在 ARM 汇编语言源程序中有些特殊助记符,它们没有相对应的操作码或者机器码,通常称为伪指令,它们所完成的操作称为伪操作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,由汇编程序在源程序的汇编期间进行处理,仅在汇编过程中起作用。

符号定义伪指令 数据定义伪指令 汇编控制伪指令 信息报告伪指令 宏指令以及其他伪指令。

Page 15: 第4章 汇编语言程序设计

符号定义伪指令符号定义伪指令

用于定义 ARM 汇编程序中的变量、对变量赋值以及定义寄存器的别名等

1 . LCLA 、 LCLL 和 LCLS

LCLA/LCLL/LCLS 局部变量名2 . GBLA 、 GBLL 和 GBLS

GBLA/GBLL/GBLS 变量名3 . SETA 、 SETL 和 SETS

变量名 SETA/SETL/SETS 表达式4 . RLIST

名称 RLIST { 寄存器列表 }

Page 16: 第4章 汇编语言程序设计

数据定义伪指令数据定义伪指令

1 . DCB标号 DCB 表达式

2 . DCW/DCWU标号 DCW/DCWU 表达式

3 . DCD/DCDU标号 DCD/DCDU 表达式

4 . DCQ/DCQU标号 DCQ/DCQU 表达式

5 . DCFD/DCFDWU标号 DCFD/DCFDU 表达式

6 . DCFS/DCFSU标号 DCFS/DCFSU 表达式

7 . SPACE标号 SPACE 表达式

8 . MAPMAP 表达式 [,基址寄存器 ]

9 . FIELD标号 FIELD 字节数

Page 17: 第4章 汇编语言程序设计

汇编控制伪指令汇编控制伪指令1 . MACRO 和 MEND

MACRO[$ 标号 ] 宏名 [$参数 1,$参数 2,…]指令序列MEND

2 . IF 、 ELSE 和 ENDIFIF 逻辑表达式

代码段 1ELSE

代码段 2ENDIF

3 . WHILE 和 WENDWHILE 逻辑表达式

代码段WEND

4 . MEXITMEXIT

Page 18: 第4章 汇编语言程序设计

其它伪指令其它伪指令

1 . ASSERTASSERT逻辑表达式

2 . AREAAREA 段名 属性

属性: DATA 定义数据段 CODE 定义代码段 READONLY 表示本段为只读 READWRITE 表示本段可读写ALIGN= 表达式对齐为 2 的表达式次方COMMON 定义一个通用段

3 . ALIGNALIGN [ 表达式 ,[, 偏移量 ]]

4 . CODE16/CODE325 . ENTRY6 . END7 . EQU名称 EQU 表达式 [,类型 ]

Page 19: 第4章 汇编语言程序设计

其它伪指令其它伪指令

8 . EXPORT/GLOBALEXPORT/GLOBAL 标号 [,WEAK]

9 . IMPORTIMPORT 标号 [,WEAK]

10 . EXTERNEXTERN 标号 [,WEAK]

11 . GET/INCLUDE GET/INCLUDE 文件名

12 . INCBININCBIN 文件名

13 . RN名称 RN 表达式

14 . ROUT名称 ROUT

Page 20: 第4章 汇编语言程序设计

汇编语言上机过程汇编语言上机过程

用 ARM 汇编语言编写的源程序,要使之运行必须经过以下几个步骤:

1.编辑汇编源程序,保存为文件名后缀是“ .s” 的文件; 2.调用汇编程序对源程序进行汇编,生成目标文件; 3.连接目标文件,生成可以放进 ARM软件仿真器进行调

试的映象文件或者可下载到 ARM 的目标板执行的二进制文件;

4.对生成的最终文件进行调试。

Page 21: 第4章 汇编语言程序设计

ARM 的开发工具 ADS1 . 2 ARM 的开发工具 ADS1 . 2

ADS1 . 2 是 ARM公司推出的一套 ARM 汇编、 C 、 C++ 的集成开发环境。包含了几个有用的开发工具,包括:

CodeWarrior IDE for the ARM Developer Suite :为 ARM的程序员管理、开发软件工程项目提供了一个简单直观、灵活的用户界面。

 AXD Debuger : AXD 是一个功能强大、使用方便的调试器。

Page 22: 第4章 汇编语言程序设计

编辑汇编语言源程序 编辑汇编语言源程序

可以使用简单的 Windows自带的记事本程序来编辑 ARM的汇编程序:

单击开始菜单程序附件记事本 敲入汇编代码保存为 .s 文件 也可以使用 CodeWarrior IDE 来编辑汇编程序: 单击 File菜单的 New菜单项 单击 Project 标签页 单击工具栏的 New Text按钮 敲入汇编代码保存为 hello.s文件 单击 Project菜单,选择“ Add *.s to project”

Page 23: 第4章 汇编语言程序设计

编译汇编语言源程序Ⅰ编译汇编语言源程序Ⅰ

ARM 的编译器有如下几种 armcc:ARM C 编译器 , 具有优化功能 ,兼容 ANSI C tcc:Thumb 的 C 编译器 , 同样具有优化功能兼容 ANSI C 。 armcpp:ARM C++ 编译器,遵循 ANSI C++ 或者 EC++ 标准

tcpp:Thubm 的 C++ 编译器,遵循 ANSI C++ 或者 EC++标准

armasm:支持 ARM 和 Thumb 的汇编器 这些编译器输出的是 ELF 格式的目标文件,可以包括

RAWF2 格式的调试信息。同时通过特殊的控制选项可以输出汇编语言文件或者列表文件。

Page 24: 第4章 汇编语言程序设计

编译汇编语言源程序Ⅱ编译汇编语言源程序Ⅱ

4 种 ARM C 和 C++ 编译器 (armcc , tcc  , 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] [-via filename]

用户通过命令行操作选项指引编译器运行。所有的选项都是以符号” -” 开始,有些选项后面还跟有参数。在大多数情况下, ARM C 和 C++ 编译器允许在选项和参数之间存在空格。

Page 25: 第4章 汇编语言程序设计

编译汇编语言源程序Ⅲ编译汇编语言源程序Ⅲ

PCS-options :指定了要使用的过程调用标准; source-language :指定了编译器可以接受的编写源程序的语言种类。对于 C 编译器默认的语言是 ANSI C ,对于 C++ 编译器默认是 ISO 标准 C++ ;

search-paths :该选项指定了对包含的文件 ( 包括源文件和头文件 ) 的搜索路径;

preprocessor-options :该选项指定了预处理器的行为,其中包括预处理器的输出和宏定义等特性;

output-format :该选项指定了编译器的输出格式,可以使用该项生成汇编语言输出列表文件和目标文件;

target-options :该选项指定目标处理器或 ARM 体系结构; debug-options :该选项指定调试信息表是否生成,和该调试信息

表生成时的格式;

Page 26: 第4章 汇编语言程序设计

编译汇编语言源程序Ⅳ编译汇编语言源程序Ⅳ code-generation-options :该选项指定了例如优化,字节顺序和由编

译器产生的数据对齐格式等选项; warning-options :该选项决定警告信息是否产生; additional-checks :该选项指定了几个能用于源码的附加检查,例

如检查数据流异常,检查没有使用的声明等; error-options :该选项可以关闭指定的可恢复的错误,或者将一些

指定的错误降级为警告; source :该选项提供了包含有 C 或 C++ 源代码的一个或多个文件名,

默认的,编译器在当前路径寻找源文件和创建输出文件。如果源文件是用汇编语言编写的 ( 也就是说该文件的文件名是以 .s 作为扩展名 ) ,汇编器将被调用来处理这些源文件。

-via filename : WINDOWS系统对命令行的长度有限制,可以通过 filename 的文件读取命令行选项。用户可以对 -via 进行嵌套调用,在文件 filename 中再通过 -via filename2 包含了另外一个文件。

Page 27: 第4章 汇编语言程序设计

连接装配汇编程序Ⅰ连接装配汇编程序Ⅰ

使用 armlink 程序对 ARM 的汇编源程序进行连接,它也可以将多个 .o目标文件连接生成最终的可执行文件。

术语 : 映像文件 (image) :是指一个可执行文件,在执行的时候被

加载到处理器中。一个映像文件可以有多个线程。它是ELF(Executable and linking format) 格式的。

段 (Section) :描述映像文件的代码或数据块。 RO : Read-only缩写。 RW :是 Read-write缩写。 ZI :是 Zero-initialized缩写。

Page 28: 第4章 汇编语言程序设计

连接装配汇编程序Ⅱ连接装配汇编程序Ⅱ

Read Only Position Independent(ROPI) :只读数据中代码和的地址在运行时候可以改变。

Read Write Position Independent(RWPI) :一个段中的可读 / 写的数据地址在运行期间可以改变。

输入段 (input section) :它包含着代码,初始化数据或描述了在应用程序运行之前必须要初始化为 0 的一段内存。

输出段 (output section) :它包含了一系列具有相同的 RO , RW 或 ZI属性的输入段。

域 (Regions) :在一个映像文件中,一个域包含了 1至 3 个输出段。多个域组织在一起,就构成了最终的映像文件。

加载时地址:映像文件载入存储器时的地址。 运行时地址:映像文件运行时的地址。

Page 29: 第4章 汇编语言程序设计

汇编程序的运行 汇编程序的运行

生成的 *.axf 文件是 ARM 的 ELF 格式的可执行映像文件;这个文件可以载入 AXD 进行仿真调试。使用armsd在终端模拟它在 ARM目标机上的运行 :执行 armsd -exec *.axf 直接在 CodeWarrior IDE 中运行映象文件:在 project窗口中点击 run按钮。在 AXD 上调试成功之后,我们可以通过 fromelf 工具

将 ELF 文件转换为二进制格式文件下载到目标板执行。转化的命令如下: fromelf *.axf -bin *

Page 30: 第4章 汇编语言程序设计

汇编程序的调试汇编程序的调试

使用 AXD 进行调试 : 编译、连接成功之后,我们可以点击project 窗口的 debug按钮启动 AXD 进行调试 :

主框架窗口上方的调试工具栏有几个常用的按钮: go :使程序运行直到下一个断点停止 step in :进入函数内部运行 Step :单步调试,每次移动一行 step out :跳出循环或函数 run to cursor :运行到光标所在的位置然后停止。

Page 31: 第4章 汇编语言程序设计

汇编语言与 C 语言混合编程技术汇编语言与 C 语言混合编程技术

ARM 体系结构支持 ARM 的汇编语言与 C 与 C++ 的混合编程 . 一般的在一个完整的程序设计的中,除了初始化部分用汇编语言完成外,其大部分的编程任务一般都用 C 或 C++完成。

Page 32: 第4章 汇编语言程序设计

汇编程序中访问 C 程序变量Ⅰ 汇编程序中访问 C 程序变量Ⅰ

在汇编的源程序中调用 C 语言风格的字符串需要使用IMPORT 伪操作。 IMPORT 相当于 C 语言中的 extern关键字,告诉编译器引用的符号不是在本文件中定义的,而是在其他的源文件中定义的。

IMPORT symbol [,WEAK]

symbol 是声明的符号的名称 ;[,WEAK] 指示编译器如果发现 symbol 在所有的源文件中都没有找到,那么它也不会产生任何的错误信息。示例见下页。

Page 33: 第4章 汇编语言程序设计

汇编程序中访问 C 程序变量Ⅱ汇编程序中访问 C 程序变量Ⅱ

C 语言代码文件 str.c, 里面只有一个简单的字符串的定义char *strhello="Hello world!\n\0";汇编代码文件 hello.s1 AREA ||.text||, CODE, READONLY 2 main PROC3 STMFD sp!,{lr}4 LDR r0,strtemp5 LDR r0,[r0]6 BL _printf7 LDMFD sp!,{pc}8 strtemp9 DCD strhello10 ENDP11 EXPORT main12 IMPORT strhello13 IMPORT _main14 IMPORT __main15 IMPORT _printf16 IMPORT ||Lib$$Request$$armlib||, WEAK17                END

Page 34: 第4章 汇编语言程序设计

C 程序中内嵌汇编指令Ⅰ C 程序中内嵌汇编指令Ⅰ

在 ARM 的 C 语言程序中我们可以使用关键字 __asm 来加入一段汇编语言的程序,格式如下:

__asm

{

instruction/*comment*/

}

Page 35: 第4章 汇编语言程序设计

C 程序中内嵌汇编指令ⅡC 程序中内嵌汇编指令Ⅱ

在 C 语言中嵌入的 ARM 汇编需要注意一些问题:在汇编指令中,可以使用表达式,使用逗号“,”作为分隔符 ;如果一条指令占用了多行,那么应该使用符号“ \”续行,如果一行中有多个汇编指令,那么应该使用“ ;” 将多个指令隔开 ,汇编中不能再使用“;”作为注释行的开头,而应该使用 C 语言中的“ /**/” 或者“ //” 进行注释 ;不要企图使用一个物理寄存器去改变一个 C 变量;对于内嵌的汇编代码用到的寄存器,编译器在编译时会自动加入保存和恢复这些寄存器的代码而不用用户去管理,除了寄存器 CPSR 和 SPSR ,其他寄存器都必须先赋值然后再读取,否则编译时将出现错误。

Page 36: 第4章 汇编语言程序设计

C 程序中内嵌汇编指令ⅢC 程序中内嵌汇编指令Ⅲ内嵌的 ARM 汇编与纯粹的 ARM 汇编的区别有 :内嵌的 ARM 汇编不支持 ADR 、 ADRL 伪指令;十六进制数使用 0x 作为前缀,而后者使用 & ;编译器在编译函数时使用 R0 、 R1 、 R2 、 R3 、 IP 和 LR 存放中间结果,因此使用这些寄存器时要特别小心;注意 C 语言中的 C 语言变量不要和物理寄存器同名,否则可能出现混乱;内嵌的汇编代码不能使用 PC 寄存器返回当前指令的地址;STM 和 LDM 指令中不能使用 C 语言表达式;不支持 BX 和 BLX ;用户可以改变处理器的模式,但仍然需要自己把处理器模式恢复过来,编译器不会自动做处理;嵌汇编指令常量前面的符号“ #” 可以省略;嵌汇编指令不支持内存分配的伪操作。

Page 37: 第4章 汇编语言程序设计

C 程序调用汇编程序 C 程序调用汇编程序

为了满足 ARM 汇编、 C 与 C++ 之间的互相调用,必须保证编写的代码遵循 APCS ( ARM 过程调用标准)。 APCS规定了子程序调用的基本规则,这些规则包括子程序调用过程中寄存器、数据栈的使用规则以及参数的传递规则。

示例见课本 P*  。

Page 38: 第4章 汇编语言程序设计

Linux 下的 ARM 汇编Linux 下的 ARM 汇编 Linux 下的 ARM 汇编指令与 Window 下的汇编相比 , 在 ARM 处理器

的指令使用方面是大同小异的 , 不同的是编译工具和 ARM 汇编的伪操作 , 其语法更类似于 gas 风格的汇编 .

GNU提供的基于 ARM平台的编译工具如下: 汇编器 arm-elf-as ,作用是将汇编语言程序转化为 ELF 格式的可重定

位目标代码。 C 编译器 arm-elf-gcc ,是 ARM 的交叉编译器,运行于 Linux平台,

它在编译时,首先通过预处理程序对源代码进行处理,然后调用 ccl 将处理后的程序转化为汇编代码,最后通过 arm-elf-as 将汇编代码编译为目标代码。

连接器 arm-elf-ld ,可以根据链接定位文件的代码区 数据区 BSS区和栈区等定位信息,将多个可重定位的目标模块链接成一个单一的,绝对定位的, ELF 格式的目标程序。

二进制转换工具 arm-elf-objcopy ,是目标格式转化工具,它能够将ELF 格式的文件转化为其他格式的文件。

Page 39: 第4章 汇编语言程序设计

Linux 汇编程序中的标号 Linux 汇编程序中的标号

标号只能由 a ~ z , A ~ Z , 0 ~ 9 “, .”, _等字符组成 .当标号为 0~ 9 的数字时为局部标号 , 局部标号可以重复出现 , 使用方法如下 :标号 f: 在引用的地方向前的标号;标号 b: 在引用的地方向后的标号使用局部符号的例子 (“@” 符号后的语句为注释 ) :1:

subs r0,r0,#1 @ 每次循环使 r0=r0-1

bne 1f @跳转到 1 标号去执行局部标号代表它所在的地址 ,因此也可以当作变量或者函数来使用。

Page 40: 第4章 汇编语言程序设计

Linux 汇编程序中的分段名 Linux 汇编程序中的分段名

段名:汇编系统预定义的段名有 : .text 、 .data 、 .bss 、 .sdata 、 .sbss等 , 每一个段以段名

为开始 , 以下一个段名或者文件结尾为结束 .用户可以通过 .section 伪操作来自定义一个段 , 格式如下 : .section section_name [, "flags"[,

%type[,flag_specific_arguments]]]示例: .section .mysection @ 自 定 义 数 据 段 , 段 名 为

“ .mysection” .align 2 .strtemp : .ascii "Temp string \n\0"

Page 41: 第4章 汇编语言程序设计

Linux 汇编程序中的宏定义Linux 汇编程序中的宏定义

格式如下 :

.macro 宏名 参数名列表 @ 伪指令 .macro 定义一个宏 宏体 .endm @.endm 表示宏结束 如果宏使用参数 ,那么在宏体中使用该参数时添加前缀“ \” 。

宏定义时的参数还可以使用默认值。 可以使用.exitm伪指令来退出宏。

Page 42: 第4章 汇编语言程序设计

Linux 下 ARM 汇编的常用伪操作 Linux 下 ARM 汇编的常用伪操作 数据定义伪操作: .byte , .short , .long , .quad  , .float , .string/.asciz/.ascii ,重复定义伪操作 .rept ,赋值语

句 .equ/.set ; 函数的定义 ; 对齐方式伪操作 .align ; 源文件结束伪操作 .end ; .include 伪操作; if 伪操作; .global/ .globl 伪操作 ; .type 伪操作 ; 列表控制语句 ; 区别于 gas 汇编的通用伪操作 , 下面是 ARM特有的伪操作

: .reg , .unreq , .code , .thumb , .thumb_func , .thumb_set  , .ltorg , .pool

Page 43: 第4章 汇编语言程序设计

ARM特有的伪操作ⅠARM特有的伪操作Ⅰ

1 . .reg: 用来给寄存器赋予别名 , 格式如下 : 别名 .req 寄存器名2. .unreq: 用来取消一个寄存器的别名 , 格式如下 :        .unreq 寄存器别名  注意被取消的别名必须事先定义过 ,否则编译器就会报错 , 这个伪操作也可以用来取消系统预制的别名 , 例如 r0, 但如果没有必要的话不推荐那样作 .

3. .code 伪操作用来选择 ARM 或者 Thumb 指令集 , 格式如下 :            .code 表达式  如果表达式的值为 16 则表明下面的指令为 Thumb 指令 , 如果表达式的值为 32 则表明下面的指令为 ARM 指令 .

4 . .thumb 伪操作等同于 .code 16, 表明使用 Thumb 指令 ,类似的 .arm等同于 .code 32

Page 44: 第4章 汇编语言程序设计

ARM特有的伪操作ⅡARM特有的伪操作Ⅱ

5 . .force_thumb 伪操作用来强制目标处理器选择 thumb的指令集而不管处理器是否支持

6 . .thumb_func 伪操作用来指明一个函数是 thumb 指令集的函数

7 . .thumb_set 伪操作的作用类似于 .set, 可以用来给一个标志起一个别名 , 比 .set 功能增加的一点是可以把一个标志标记为 thumb 函数的入口 , 这点功能等同于 .thumb_func

8 . .ltorg 用于声明一个数据缓冲池 (literal pool) 的开始 ,它可以分配很大的空间。

9 . .pool 的作用等同 .ltorg

Page 45: 第4章 汇编语言程序设计

程序示例程序示例

@ 文件 "hello.S".section .rodata @只读数据段.align 2

.strhello:.ascii "Hello world ! \n\0"

.text.align 2.global main.type main,function

main:stmfd sp!, {lr} @保存返回地址ldr r0, .strhellotemp @取字符串的地址作为参数bl printf @调用 printf打印ldmfd sp!, {pc} @恢复返回地址

 .strhellotemp:

.word .strhello @ 存储字符串 .strhello 的地址

Page 46: 第4章 汇编语言程序设计

程序优化程序优化 编译器对程序进行一定的优化是非常有必要的,高级语言

的程序可以被转化为汇编语言的指令形式。优化技术是全面而非片面的。通常优化的方法有以下几种:

简化算术表达式 废代码的清除 循环优化

Page 47: 第4章 汇编语言程序设计

性能测试性能测试 对嵌入式系统进行性能测试可以衡量系统的实时性,分析嵌

入式软件的优劣,同时分析程序的执行时间可以帮助我们分析 CPU 功耗等特性。

精确的测量程序的执行时间意义不大,我们可以用下面的三个概念分析程序的执行时间:

平均执行时间:多次测量程序的执行时间取平均值。 最坏执行时间:程序的大量输入序列所产生的最长的程序执

行时间。有些情况下,产生最坏执行时间的输入数值并不容易确定,需要对程序的代码进行分析产生特殊的测试用例。

最佳执行时间:大量输入序列的测试中记录嵌入式程序运行最短的那一个时间。