第 9 章 arm 汇编语言程序设计基础

66
第 9 第 ARM 第第第第第第第第第第

Upload: adrina

Post on 25-Jan-2016

138 views

Category:

Documents


2 download

DESCRIPTION

第 9 章 ARM 汇编语言程序设计基础. ADS IDE (集成开发环境 ). ARM 应用软件的开发工具根据功能的不同,可以分为编辑软件、编译软件、汇编软件、链接软件、调试软件、嵌入式实时操作系统、函数库、评估板, JTAG 仿真器以及在线仿真器等。目前有多家公司可以提供以上不同类型的开发工具,用户采用 ARM 处理器进行嵌入式系统开发时,选择合适的开发工具可以加快开发进度,节省开发成本。. ADS 工具包的组成. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 第 9 章  ARM 汇编语言程序设计基础

第 9 章 ARM 汇编语言程序设计基础

Page 2: 第 9 章  ARM 汇编语言程序设计基础

ADS IDE (集成开发环境 ) ARM 应用软件的开发工具根据功能的不

同,可以分为编辑软件、编译软件、汇编软件、链接软件、调试软件、嵌入式实时操作系统、函数库、评估板, JTAG仿真器以及在线仿真器等。目前有多家公司可以提供以上不同类型的开发工具,用户采用 ARM 处理器进行嵌入式系统开发时,选择合适的开发工具可以加快开发进度,节省开发成本。

Page 3: 第 9 章  ARM 汇编语言程序设计基础

ADS 工具包的组成 ADS 是 ARM 公司推出的集成开发工具包,是

专门用于 ARM 相关应用开发和调试的综合性软件。目前常用的版本是 1.2 ,在功能和易用性上比早期的 SDT 都有提高,是一款功能强大又易于使用的开发工具。 ARM ADS 包含有编译器、链接器、 CodeWarrior IDE 、调试器、指令集模拟器、 ARM 开发包和应用库等部分,可以用 ADS 来开发、编译、调试采用包括 C 、C++ 和 ARM 汇编语言编写的程序。

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

ADS 工具包的组成 1. 编译器 ADS 提供多种编译器,以支持 ARM 和 Thumb

指令的编译。 2. 链接器 Armlink ( ARM 链接器)可以将编译得到的一

个或多个目标文件和相关的一个或多个库文件进行链接,生成一个可执行文件,也可以将多个目标文件部分链接成一个目标文件,以供进一步的链接。

Page 5: 第 9 章  ARM 汇编语言程序设计基础

ADS 工具包的组成 3. CodeWarrior IDE CodeWarrior IDE (集成开发环境)包括工程

管理器、代码生成接口、语法敏感编辑器、源文件和类浏览器、源代码版本控制系统接口以及文本搜索引擎等。 ADS 仅在其 PC 机版本中集成了该 IDE 。

CodeWarrior IDE 为管理和开发项目提供了简单多样化的图形用户界面,用户可以使用 ADS的 CodeWarrior IDE 为 ARM 和 Thumb 处理器开发用 C 、 C++ 或者 ARM 汇编语言编写的程序代码。

Page 6: 第 9 章  ARM 汇编语言程序设计基础

ADS 工具包的组成 ( 1 )调试器类型 ADS 中包含有 3 个调试器,分别是 ARM

扩展调试器 AXD ( ARM eXtended Debugger.

( 2 )调试方式 在 ARM 体系中,可以选择 Multi-ICE

( Multi-processor in-circuit emulator ) ARMulator 或 Angel 多种调试方式。

Page 7: 第 9 章  ARM 汇编语言程序设计基础

ADS 工具包的组成 5. ARM 开发包和函数库 ARM 开发包由一些底层的例程和库组成,

可以帮助用户快速开发基于 ARM 的应用程序和操作系统。

ADS 的 ARM 应用库完善并增强了 SDT中的函数库,同时还包括一些非常有用的源码例程。

Page 8: 第 9 章  ARM 汇编语言程序设计基础

ADS 开发工具集 1 .命令行开发工具 (1)armcc armcc 是 ARM C 编译器。在命令控制台环境下,输

入命令: C:> armcc –help 可以查看 armcc 的语法格式以及最常用的一些操作选项。

( 2 ) armcpp armcpp 是 ARM C++ 编译器。它将 ISO C++ 或 EC

++ 编译成 32 位 ARM 指令代码。 (3) tcc tcc 是 Thumb C 编译器。该编译器通过了 Plum Hal

l C Validation Suite 为 ANSI 一致性的测试。 tcc 将 ANSI C 源代码编译成 16 位的 Thumb 指令代码。

Page 9: 第 9 章  ARM 汇编语言程序设计基础

ADS 开发工具集(4) tcpp tcpp 是 Thumb C++ 编译器。 它将 ISO C++

和 EC++ 源码编译成 16 位 Thumb 指令代码。 (5) armsm armsm 是 ARM 和 Thumb 的汇编器 . 它对

用 ARM 汇编语言和 Thumb 汇编语言写的源代码进行汇编。

(6) armlink armlink 是 ARM 连接器。 (7) armsd armsd 是 ARM 和 Thumb 的符号调试器。

Page 10: 第 9 章  ARM 汇编语言程序设计基础

ADS 开发工具集 2 . GUI 开发环境 ADS GUI 开发环境主要包含 Code Warrior 和

AXD ,其中 Code Warrior 是用于编译和链接的集成开发工具,而 AXD则是支持单步执行、断点设置等功能的集成调试工具。

( 1 ) Code Warrior Code Warrior for ARM 是一套完整的集成开发

工具,充分发挥了 ARM RISC 指令系统的优势 , 使产品开发人员能够很好的应用尖端的片上系统技术 . 该工具是专为基于 ARM RISC 的处理器而设计的 。

Page 11: 第 9 章  ARM 汇编语言程序设计基础

ADS 开发工具集 ( 2 ) AXD AXD 调试器本身是一个软件,用户通过这个软

件可以对包含有调试信息的、正在运行的可执行代码进行变量的查看、断点的设置、单步执行等调试操作。在 ARM 体系中,它有 Multi-ICE 、 ARMulator 和 Angel 等几种方式。 AXD可以在 Windows 和 UNIX 下进行程序的调试,它为用 C 、 C++ 和汇编语言的源代码提供了一个全面的 Windows 和 UNIX 环境。

Page 12: 第 9 章  ARM 汇编语言程序设计基础

ADS 开发工具集 3 、 实用程序 ADS 提供以下的实用工具来配合前面介绍的命令行开发工具的使用。

fromELF是 ARM 映像文件转换工具。 armar 是 ARM 库函数生成器。 Flash downloader 用于把二进制映像文

件下载到 ARM 嵌入式设备上的 Flash 存储器中。

Page 13: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编伪指令 在 ARM 汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,也就是不会生成机器码,仅仅是在编译器软件中起着格式化的作用,通常称这些特殊指令助记符为伪指令。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。 在 ARM 的汇编程序中,有如下几种伪指令:数据常量定义伪指令、数据变量定义伪指令、内存分配伪指令及其他伪指令。

Page 14: 第 9 章  ARM 汇编语言程序设计基础

1 数据常量定义伪指令 数据常量定义伪指令 EQU用于为程序中的常量、标号等定义一个等效的字符名称,类似于 C 语言中的 #define 。 EQU语法格式 : 名称 EQU 表达式 { ,类型 } ;其中 EQU 可用 “ * ” 代替。 名称为 EQU 伪指令定义的字符名称,当表达式为 32 位的常量时,可以指定表达式的数据类型,可以有以下三种类型: CODE16 、 CODE32 和 DATA 。

Page 15: 第 9 章  ARM 汇编语言程序设计基础

2 数据变量定义伪指令 (Cont.) 数据变量定义伪指令用于定义 ARM 汇编程序中的变量、对变量赋值以及定义寄存器的别名等操作。常见的数据变量定义伪指令有如下几种: ( 1 ) GBLA 、 GBLL 和 GBLS 语法格式: GBLA ( GBLL 或 GBLS ) 全局变量名 GBLA 、 GBLL 和 GBLS 伪指令用于定义全局变量,并将其初始化。其中: ① GBLA 用于定义一个全局的数字变量,并初始化为 0 ; ② GBLL用于定义一个全局的逻辑变量,并初始化F(假);

③ GBLS 用于定义一个全局的字符串变量,并初始化为空;

Page 16: 第 9 章  ARM 汇编语言程序设计基础

2 数据变量定义伪指令 (Cont.) ( 2 ) LCLA 、 LCLL 和 LCLS

语法格式: LCLA ( LCLL 或 LCLS ) 局部变量名 LCLA 、 LCLL 和 LCLS 伪指令用于定义一个 ARM 程序中的局部变量,并将其初始化。其中: ① LCLA伪指令用于定义一个局部的数字变量,并初始化为 0 ; ② LCLL 伪指令用于定义一个局部的逻辑变量,并初始化为 F(假); ③ LCLS 伪指令用于定义一个局部的字符串变量,并初始化为空;

Page 17: 第 9 章  ARM 汇编语言程序设计基础

2 数据变量定义伪指令 (Cont.) ( 3 ) SETA 、 SETL 和 SETS

语法格式:变量名 SETA ( SETL 或 SETS ) 表达式 伪指令 SETA 、 SETL 、 SETS 用于给一个已经定义的全局变量或局部变量赋值。 ① SETA 伪指令用于给一个数学变量赋值; ② SETL 伪指令用于给一个逻辑变量赋值; ③ SETS 伪指令用于给一个字符串变量赋值;

Page 18: 第 9 章  ARM 汇编语言程序设计基础

2 数据变量定义伪指令 (Cont.) ( 4) RLIST

语法格式:名称 RLIST { 寄存器列表 } RLIST 伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在 ARM 指令 LDM/STM 中使用。在 LDM/STM 指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。

Page 19: 第 9 章  ARM 汇编语言程序设计基础

3 内存分配伪指令 内存分配伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪指令有如下几种:

( 1 ) DCB 语法格式: 标号 DCB 表达式

(2) DCW (或 DCWU) 语法格式: 标号 DCW (或 DCWU ) 表达式

Page 20: 第 9 章  ARM 汇编语言程序设计基础

3 内存分配伪指令 (Cont.) ( 3 ) DCD (或 DCDU)

语法格式: 标号 DCD (或 DCDU ) 表达式

( 4) DCFD (或 DCFDU) 语法格式: 标号 DCFD (或 DCFDU ) 表达式

( 5) DCFS (或 DCFSU) 语法格式: 标号 DCFS (或 DCFSU ) 表达式

Page 21: 第 9 章  ARM 汇编语言程序设计基础

3 内存分配伪指令 (Cont.) (6) DCQ( 或 DCQU)

语法格式: 标号 DCQ (或 DCQU ) 表达式

( 7) SPACE 语法格式: 标号 SPACE 表达式

( 8) MAP 语法格式: MAP 表达式 { ,基址寄存器 }

( 9) FILED 语法格式:标号 FIELD 表达式

Page 22: 第 9 章  ARM 汇编语言程序设计基础

4 汇编控制伪指令 汇编控制伪指令用于控制汇编程序的执行流程,

常用的汇编控制伪指令包括以下几条: ( 1 ) IF 、 ELSE 、 ENDIF 语法格式: IF 逻辑表达式

指令序列 1 ELSE

指令序列 2 ENDIF

Page 23: 第 9 章  ARM 汇编语言程序设计基础

4 汇编控制伪指令 (Cont.) ( 2 ) WHILE 、 WEND

语法格式: WHILE 逻辑表达式 指令序列 WEND

( 3 ) MEXIT 语法格式: MEXIT MEXIT 用于从宏定义中跳转出去。

Page 24: 第 9 章  ARM 汇编语言程序设计基础

4 汇编控制伪指令 (Cont.) ( 4 ) MACRO 、 MEND

语法格式: MACRO $ 标号 宏名 $ 参数 1 , $ 参数 2 ,…… 指令序列 MEND MACRO 、 MEND伪指令可以将一段代码定义为一个整体,然后就可以在程序中通过宏指令多次调用该段代码。

Page 25: 第 9 章  ARM 汇编语言程序设计基础

5 其他常用的伪指令 还有一些其他的伪指令,在汇编程序中经常会被使用,主要包括 AREA 、 ALIGN 、 CODE16、 CODE32 、 ENTRY、END 、 EXPOR (或 GLOBAL) IMPORT 、 EXTERN 、 GET (或 INCLUDE )INCBIN 、 RN 、 ROUT 等。

Page 26: 第 9 章  ARM 汇编语言程序设计基础

5 其他常用的伪指令 (Cont.) ( 1 ) AREA

语法格式: AREA 段名 属性 1 ,属性 2 ,…… AREA 伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用 “ | ” 括起来,如 |1_test| 。属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。

Page 27: 第 9 章  ARM 汇编语言程序设计基础

5 其他常用的伪指令 (Cont.) ( 2 ) ALIGN 语法格式: ALIGN { 表达式 { , 偏移量 }} ( 3 ) CODE16、 CODE32

语法格式: CODE16 (或 CODE32 ) ( 4) ENTRY

语法格式: ENTRY ……

Page 28: 第 9 章  ARM 汇编语言程序设计基础

5 其他常用的伪指令 (Cont.) ( 5) END

语法格式: END ( 6) EXPORT (或 GLOBAL)

语法格式: EXPORT 标号 {[WEAK]} (7) IMPORT

语法格式: IMPORT 标号 {[WEAK]}

Page 29: 第 9 章  ARM 汇编语言程序设计基础

5 其他常用的伪指令 (Cont.) ( 8) EXTERN

语法格式: EXTERN 标号 {[WEAK]} ( 9) GET (或 INCLUDE )

语法格式: GET 文件名 ( 10) INCBIN

语法格式: INCBIN 文件名 ( 11 ) RN

语法格式: 名称 RN 表达式

Page 30: 第 9 章  ARM 汇编语言程序设计基础

ARM 的汇编语言结构 在 ARM ( Thumb )汇编语言程序中,以相对独立的

指令或数据序列的程序段为单位组织程序代码。段可以分为代码段和数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。一个汇编程序至少应该有一个代码段,也可以分割为多个代码段和数据段,多个段在程序编译链接时最终形成一个可执行的映象文件。可执行映象文件通常由以下几部分构成:

① 一个或多个代码段,代码段的属性为只读。 ② 零个或多个包含初始化数据的数据段,数据段的属性为可读写。

③ 零个或多个不包含初始化数据的数据段,数据段的属性为可读写。

Page 31: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言的语句格式 1. 基本语句格式 ARM ( Thumb )汇编语言的语句格式为: {标号 } {指令或伪指令 } { ;注释 } 规则 : ① 如果一条语句太长,可将其分为若干行来书写,在行的末用续行符“ \”来标识下一行与本行为同一条语句。

② 每一条指令的助记符可以全部用大写、或全部用小写,但不能在一条指令中大、小写混用。

Page 32: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言的语句格式 (Cont.) 2. 汇编语言程序中常用的符号 在汇编语言程序设计中,可以使用各种符号代替地址、变量和常量等,以增加程序的可读性。以下为符号命名的约定:

① 符号名不应与指令或伪指令同名 ② 符号在其作用范围内必须唯一。 ③ 符号区分大小写,同名的大、小写符号被视为两个不同的符号。

④ 自定义的符号名不能与系统保留字相同。

Page 33: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言的语句格式 (Cont.) 3. 程序中的常量 程序中的常量是指其值在程序的运行过程中不

能被改变的量。 ARM ( Thumb )汇编程序所支持的常量有逻辑常量、数字常量和字符串常量。

① 数字常量一般为 32 位的整数,无符号常量取值范围为 0 ~ 232-1 ,有符号常量取值范围为 -231~ 231-1 。

② 逻辑常量只有两种取值:真或假。 ③ 字符串常量为一个固定的字符串,一般用

来提示程序运行时的信息。

Page 34: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言的语句格式 (Cont.) 4. 汇编语言程序中的变量 程序中的变量是指其值在程序的运行过程中可以改变

的量。 ① 逻辑变量用于在程序的运行中保存逻辑值(真 /假)。

② 数字变量用于在程序的运行中保存数字值,但数字值的大小不应超出数字变量所能表示的范围。

③ 字符串变量用于在程序的运行中保存一个字符串,但字符串的长度不应超出字符串变量所能表示的范围。

Page 35: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言的语句格式 (Cont.) 5. 程序中的变量代换 程序中的变量可通过代换操作取得一个

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

Page 36: 第 9 章  ARM 汇编语言程序设计基础

基于 Windows 下 ADS 的汇编语言程序结构

ADS 环境下的 ARM 汇编语言程序结构与其它环境下的汇编语言程序结构大体相同,整个程序也是以段为单元来组织代码。其语法规则总结如下:

① 所有标号必须在一行的顶格书写,其后不要添加“:”号;

② 所有的指令均不能顶格写; ③ 大小写敏感(可以全部大写或全部小写,但不能大小写混合使用);

④ 注释使用分号“ ;” 。

Page 37: 第 9 章  ARM 汇编语言程序设计基础

基于 Linux 下 GCC 的汇编语言程序结构

Linux下 GCC 的汇编语言结构与其它环境下的汇编语言结构相似,整个程序都是以程序段为单位来组织代码,但是在语言规则上与 ADS 环境下的 ARM 汇编语言规则有明显的区别。现将 Linux下 GCC 的汇编语言规则总结如下:

① 所有标号必须在一行的顶格书写,并且其后必须添加“ :”号;

② 所有的指令均不能顶格写; ③ 大小写敏感(可以全部大写或全部小写,但不能

大小写混合使用); ④ 注释使用分号“@” (注释的内容由“@” 号起到此行结束,注释可以在一行的顶格书写);

Page 38: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言程序调试 无论进行嵌入式系统软件开发还是硬件电路设计,调试永远是不可缺少的、非常重要的一个环节。通常嵌入式系统的调试方法和类型有很多种,最为常见的包括软件模拟调试、硬件仿真器在线调试、 Wiggler 线缆调试和 Linux环境下的 gdb 程序调试。

Page 39: 第 9 章  ARM 汇编语言程序设计基础

ADS 软件模拟环境下的程序调试 ADS 软件模拟调试是利用 ARMUL.dll 提

供的一个软 ARM内核,调试工具和待调试的嵌入式软件都在主机上运行,由主机提供一个模拟的目标运行环境,可以进行语法和逻辑上的调试。它的优点是简单方便,不需要嵌入式目标板,软件的调试功能较强;功能有限,不能进行实时联机调试。

Page 40: 第 9 章  ARM 汇编语言程序设计基础

ADS硬件仿真器环境下的程序调试 在 ADS 环境下利用 JTAG硬件仿真器可

以实现联机调试,即在线调试嵌入式设备的 Flash 中的程序或者 SDRAM 中的程序。由于仿真器自成体系,调试时既可以连接目标板,也可以不连接目标板,当然仿真器的价格也相对比较贵。一般在程序的前期开发,通常让程序只在 SDRAM 中调试运行,最后才下载到 Flash中进行调试运行。

Page 41: 第 9 章  ARM 汇编语言程序设计基础

ADS硬件仿真器环境下的程序调试 (Cont.) ARM 仿真器是通过内部硬件实现 PC 并

口协议到串行 JTAG ( Jiont Test Action Gruop )协议的转换。利用高速 JTAG串行扫描链,通过调试通信通道( Debug Communications Channel,DCC )连接 ARM核心内嵌的名为“ Embedded-ICE”的调试逻辑,调试逻辑实时监测 ARM核心的寄存器、数据总线和地址总线。

Page 42: 第 9 章  ARM 汇编语言程序设计基础

ADS硬件仿真器环境下的程序调试 (Cont.) 1. Multi-ICE server 软件的安装

Page 43: 第 9 章  ARM 汇编语言程序设计基础

ADS硬件仿真器环境下的程序调试 (Cont.)

2 .运行 Multi-ICE server 保证硬件正确连接后,即可运行 Multi-ICE server ,默认情况下, server 会用自动配置来连接目标器件。当然,可以在 settings 菜单下选择配置的方式,一般选择 Atuo-Configure即可。

如果正确连接到一个 ARM内 核的嵌入式目标板,将显示 图。

Page 44: 第 9 章  ARM 汇编语言程序设计基础

ADS硬件仿真器环境下的程序调试 (Cont.) 3 . 配置 ADS 以支持 JTAG 仿真器 启动 ADS 的调试器 AXD后,从菜单“ Option”中选

择“ Configure Target”,在弹出的窗口中,选择 Multi-ICE ,如果没有此项,则需要将 Multi-ICE驱动添加到对话框中。如图所示。

Page 45: 第 9 章  ARM 汇编语言程序设计基础

ADS Wiggler 调试电缆环境下的程序调试

Wiggler 调试电缆实际上可以看出就是一个简易的 JTAG“仿真器”,它也支持 ADS 集成开发环境和在线联机调试,支持单步、全速及断点等调试功能。

Page 46: 第 9 章  ARM 汇编语言程序设计基础

ADS Wiggler 调试电缆环境下的程序调试 (Cont.)

1. Wiggler JTAG 调试电缆的驱动安装 要使用 Wiggler JTAG 调试电缆来调试 ARM

处理器,除了 ADS1.2 集成开发环境外,还需要安装一个 ARM 调试代理,一般使用 H-JTAG 软件, H-JTAG 软件的特点如下:

① 支持 ARM7/ARM9,支持自动检测和手动指定内核;

② 使用 RDI 接口,支持 SDT2.51 、 ADS1.2 、REALVIEW 和 IAR 集成开发环境;

③ 支持 2 个硬件断点或数量不限的软件断点;

Page 47: 第 9 章  ARM 汇编语言程序设计基础

④ 支持 ARM/Thumb 模式; ⑤ 支持 Little Endian & BIG Endian 模式; ⑥ 支持 Semihosting 调试; ⑦ 支持 Wiggler 、 SDT JTAG 和自定义接口。 首先,用鼠标双击 H-JTAG 软件的安装文件 H-

JTAG V0.2.exe ,启动 H-JTAG 安装界面,按照提示操作完成安装。

Page 48: 第 9 章  ARM 汇编语言程序设计基础

ADS Wiggler 调试电缆环境下的程序调试 (Cont.)

2. 运行 H-JATG 软件 接着,将 Wiggler JTAG 调试电缆一头

通过并口延长线与 PC 机的并口连接,另一头接到嵌入式目标板的 JTAG插座上。然后启动 H-JTAG 。 H-JTAG会自动检测 ARM 内核,如果 JTAG 连接正确将会在 H-JTAG主窗口中显示处理器的型号 .

Page 49: 第 9 章  ARM 汇编语言程序设计基础

ADS Wiggler 调试电缆环境下的程序调试 (Cont.)

3. 配置 ADS 以支持 JTAG 仿真器 启动 ADS 的调试器 AXD后,从菜单“ Optio

n”中选择“ Configure Target”,在弹出的窗口中,添加或选择 H-JTAG.dll (如图所示)。

Page 50: 第 9 章  ARM 汇编语言程序设计基础

Linux环境下的 gdb 程序调试 Linux下提供了一个叫 gdb 的 GNU调试程序,主要用来调试 C 、 C++ 等应用程序。它可以提供: ① 监视程序中变量的值; ② 设置断点以使程序在指定的代码行上暂停执行; ③ 单步执行;

语法格式: gdb <fname>

Page 51: 第 9 章  ARM 汇编语言程序设计基础

gdb 基本命令

Page 52: 第 9 章  ARM 汇编语言程序设计基础

ARM 汇编语言与 C 语言混合编程 ARM 体系结构支持 C/C++ 以及汇编语言的混

合编程,在一个完整的程序设计中,除了初始化部分用汇编完成以外,其主要的编程任务一般都用 C/C++ 完成。

汇编语言和 C/C++ 的混合编程通常有以下几种方式:

① 汇编程序中调用 C 程序 ② C 程序中调用汇编程序 ③ C 程序中内嵌汇编语句 ④ 从汇编程序中访问 C 程序变量

Page 53: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS 基本的 ATPCS规定了在混合编程时子程序调

用的一些基本规则,主要包括寄存器的使用、堆栈的使用、参数传递和子程序结果的返回等方面的规则。

1. 寄存器的使用规则 ① 程序通过寄存器 R0~R3 来传递参数,这时这些寄存器可以记作 A0~A3 ,被调用的子程序在返回前无需恢复寄存器 R0~R3 的内容。

Page 54: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS (Cont.) ② 在子程序中,使用 R4~R11 来保存局

部变量,这时这些寄存器可以记作 V1~V8。

③ 寄存器 R12 用作子程序间 scratch寄存器,记作 IP ,在子程序的连接代码段中经常会有这种使用规则。

Page 55: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS (Cont.) ④ 寄存器 R13 用作数据栈指针,记做 SP ,在子程序中寄存器 R13 不能用做其他用途。

⑤ 寄存器 R14用作连接寄存器,记作 LR ,它用于保存子程序的返回地址。

⑥ 寄存器 R15是程序计数器,记作 PC ,它不能用作其他用途。

⑦ ATPCS 中的各寄存器在 ARM 编译器和汇编器中都是预定义的。

Page 56: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS (Cont.) 2. 堆栈的使用规则 栈指针通常可以指向不同的位置,当栈指针指向栈顶元素时,称为 FULL栈。当栈指针指向与栈顶元素相邻的一个元素时 , 称为 Empty 栈。 数据栈的增长方向也可以不同,当数据栈向内存减小的地址方向增长时,称为 Descending栈;反之称为 Ascending栈。

Page 57: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS (Cont.) 3. 参数的传递规则 根据参数个数是否固定,可以将子程序

分为参数个数固定的子程序和参数个数可变的子程序,这两种子程序的参数传递规则不同的。

① 参数个数可变的子程序参数传递规则。 ② 参数个数固定的子程序参数传递规则。

Page 58: 第 9 章  ARM 汇编语言程序设计基础

基本的 ATPCS (Cont.) 4. 子程序结果返回规则 ① 结果为一个 32 位的整数时,可通过寄存器 R0返回。 ② 结果为一个 64位整数时,可以通 R0和 R1返回,依此类推。

③ 结果为一个浮点数时,可以通过浮点运算部件的寄存器 f0, d0或者 s0来返回。

④ 结果为一个复合的浮点数时,可以通过寄存器 f0-fN 或者 d0~dN 来返回。

⑤ 对于位数更多的结果,则需要通过调用内存来传递。

Page 59: 第 9 章  ARM 汇编语言程序设计基础

汇编程序中调用 C 程序 2. C 语言文件 /*C file, called by asmfile */ int cFun(int a, int b, int c) { return a + b + c; } 这里的参数传递是利用寄存器 r0~r2 。需要指

出的是当函数的参数个数大于 4时就要借助堆栈。

Page 60: 第 9 章  ARM 汇编语言程序设计基础

C 程序中调用汇编程序 在汇编程序中使用 EXPORT伪指令声明

程序,使得本程序可以被其他的程序调用;在 C 语言中使用 EXTERN 关键词声明该汇编程序,这样就可以在 C 中使用该函数了。从 C 的角度,并不知道该函数的实现是用 C 还是汇编。

Page 61: 第 9 章  ARM 汇编语言程序设计基础

C 程序中内嵌汇编语句 在 C 中内嵌的汇编指令支持大部分的 ARM 和 Thumb

指令,不过其使用与汇编文件中的指令有些不同,存在一些限制,主要有下面几个方面:

① 不能直接向 PC寄存器赋值,程序跳转要使用 B或者 BL指令;

② 在使用物理寄存器时,不要使用过于复杂的 C表达式,避免物理寄存器冲突;

③ R12 和 R13 可能被编译器用来存放中间编译结果; ④ 一般不要直接指定物理寄存器,而让编译器进行分配;

Page 62: 第 9 章  ARM 汇编语言程序设计基础

从汇编程序中访问 C 程序变量 在 C 程序中声明的全局变量可以被汇编程序通

过地址间接访问,具体访问方法如下: ① 使用 IMPORT伪指令声明该全局变量。 ② 使用 LDR 指令读取该全局变量的内存地址,

通常该全局变量的内存地址值存放在程序的数据缓冲区中。

③ 根据该数据的类型,使用相应的 LDR 指令读取该全局变量的值,使用相应的 STR 指令修改该全局变量的值。

Page 63: 第 9 章  ARM 汇编语言程序设计基础

从汇编程序中访问 C 程序变量(Cont.) 各数据类型及其对应的 LDR/STR 指令如下: ① 对于无符号的 char 类型的变量通过指令 LD

RB/STRB来读写。 ② 对于无符号的 short 类型的变量通过指令 LD

RH/STRH读写。 ③ 对于 int 类型的变量通过指令 LDR/STR 来读

写。 ④ 对于有符号的 char 类型的变量通过指令 LD

RSB来读取。 ⑤ 对于有符号的 char 类型的变量通过指令 ST

RB来写入。

Page 64: 第 9 章  ARM 汇编语言程序设计基础

⑥ 对于有符号的 short 类型的变量通过指令 LDRH 来读取。

⑦ 对于有符号的 short 类型的变量通过指令 LDRH 来写入。

⑧ 对于小于 8个字的结构型变量,可以通过一条 LDM/STM 指令来读 /写整个变量。

⑨ 对于结构型变量的数据成员,可以使用相应的 LDR/STR 指令来访问,这时必须知道该数据成员相对于结构型变量开始地址的偏移量。

Page 65: 第 9 章  ARM 汇编语言程序设计基础

从汇编程序中访问 C 程序变量(Cont.) 下面是一个在汇编程序中访问 C 程序全局变量的例子。 AREA global_exp, CODE, READONLY EXPORT asmsub IMPORT globv ;声明全局变量 asmsub LDR r1, = globv ;将内存地址读入到 R1 中 LDR r0, [r1] ;将数据读入到 R0中 ADD r0, r0, #2 STR r0, [r1] ;修改 后再将值赋予变量 MOV pc, lr END

Page 66: 第 9 章  ARM 汇编语言程序设计基础

从汇编程序中访问 C 程序变量(Cont.) 程序中,变量 globv1 是在 C 程序中声明

的全局变量,在汇编程序中首先使用 IMPORT伪指令声明该变量,再将其内存地址读入到寄存器 R1 中,将其值读入到寄存器 R0中,修改后再将寄存器 R0的值赋予变量 globv。