配色: 字号:
《ARM9嵌入式系统设计基础教程》第9章ARM汇编语言程序设计基础
2023-05-24 | 阅:  转:  |  分享 
  
第9章 ARM汇编语言程序设计基础ADS IDE(集成开发环境)ARM应用软件的开发工具根据功能的不同,可以分为编辑软件、编译软件、汇编软件
、链接软件、调试软件、嵌入式实时操作系统、函数库、评估板,JTAG仿真器以及在线仿真器等。目前有多家公司可以提供以上不同类型的开发
工具,用户采用ARM处理器进行嵌入式系统开发时,选择合适的开发工具可以加快开发进度,节省开发成本。 ADS工具包的组成 ADS是A
RM公司推出的集成开发工具包,是专门用于ARM相关应用开发和调试的综合性软件。目前常用的版本是1.2,在功能和易用性上比早期的SD
T都有提高,是一款功能强大又易于使用的开发工具。ARM ADS包含有编译器、链接器、CodeWarrior IDE、调试器、指令集
模拟器、ARM开发包和应用库等部分,可以用ADS来开发、编译、调试采用包括C、C++和ARM汇编语言编写的程序。 ADS工具包的组
成1. 编译器ADS提供多种编译器,以支持ARM和Thumb指令的编译。2. 链接器Armlink(ARM链接器)可以将编译得到的
一个或多个目标文件和相关的一个或多个库文件进行链接,生成一个可执行文件,也可以将多个目标文件部分链接成一个目标文件,以供进一步的链
接。ADS工具包的组成3. CodeWarrior IDECodeWarrior IDE(集成开发环境)包括工程管理器、代码生成接
口、语法敏感编辑器、源文件和类浏览器、源代码版本控制系统接口以及文本搜索引擎等。ADS仅在其PC机版本中集成了该IDE。CodeW
arrior IDE为管理和开发项目提供了简单多样化的图形用户界面,用户可以使用ADS的CodeWarrior IDE为ARM和T
humb处理器开发用C、C++或者ARM汇编语言编写的程序代码。ADS工具包的组成(1)调试器类型ADS中包含有3个调试器,分别是
ARM扩展调试器AXD(ARM eXtended Debugger.(2)调试方式在ARM体系中,可以选择Multi-ICE(Mu
lti-processor in-circuit emulator)ARMulator或Angel多种调试方式。ADS工具包的组成
5. ARM开发包和函数库ARM开发包由一些底层的例程和库组成,可以帮助用户快速开发基于ARM的应用程序和操作系统。ADS的ARM
应用库完善并增强了SDT中的函数库,同时还包括一些非常有用的源码例程。ADS开发工具集 1.命令行开发工具(1)armccarmc
c是 ARM C 编译器。在命令控制台环境下,输入命令:C:> armcc –help可以查看 armcc 的语法格式以及最常用的
一些操作选项。(2)armcpparmcpp 是 ARM C++ 编译器。它将 ISO C++ 或 EC++ 编译成 32 位 A
RM 指令代码。(3) tcctcc 是 Thumb C 编译器。该编译器通过了 Plum Hall C Validation S
uite 为 ANSI 一致性的测试。tcc 将 ANSI C 源代码编译成 16 位的 Thumb 指令代码。ADS开发工具集(
4) tcpptcpp 是 Thumb C++ 编译器。 它将 ISO C++ 和 EC++ 源码编译成 16 位 Thumb 指
令代码。(5) armsmarmsm 是 ARM 和 Thumb 的汇编器 . 它对用 ARM 汇编语言和 Thumb 汇编语言写
的源代码进行汇编。(6) armlinkarmlink是 ARM 连接器。(7) armsdarmsd是 ARM 和 Thumb
的符号调试器。ADS开发工具集2.GUI 开发环境 ADS GUI开发环境主要包含Code Warrior 和 AXD,其中Cod
e Warrior是用于编译和链接的集成开发工具,而AXD则是支持单步执行、断点设置等功能的集成调试工具。(1)Code Warr
ior Code Warrior for ARM是一套完整的集成开发工具,充分发挥了 ARM RISC指令系统的优势, 使产品开
发人员能够很好的应用尖端的片上系统技术 . 该工具是专为基于 ARM RISC 的处理器而设计的 。 ADS开发工具集(2)AXD
AXD调试器本身是一个软件,用户通过这个软件可以对包含有调试信息的、正在运行的可执行代码进行变量的查看、断点的设置、单步执行等调试
操作。在ARM体系中,它有Multi-ICE、ARMulator和Angel等几种方式。AXD可以在Windows和UNIX下进行
程序的调试,它为用C、C++和汇编语言的源代码提供了一个全面的Windows和UNIX环境。ADS开发工具集3、 实用程序ADS
提供以下的实用工具来配合前面介绍的命令行开发工具的使用。fromELF是 ARM 映像文件转换工具。armar是ARM库函数生成器
。Flash downloader用于把二进制映像文件下载到ARM嵌入式设备上的 Flash 存储器中。ARM汇编伪指令 在 AR
M 汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的操作码,也就是不会生成机器码,仅仅是在编译
器软件中起着格式化的作用,通常称这些特殊指令助记符为伪指令。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在
汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。???? ???? 在 ARM 的汇编程序中,有如下几种伪指令:数据常量定
义伪指令、数据变量定义伪指令、内存分配伪指令及其他伪指令。1 数据常量定义伪指令 数据常量定义伪指令EQU用于为程序中的常量、标
号等定义一个等效的字符名称,类似于 C 语言中的#define 。 ?? EQU语法格式 :??名称 EQU 表达式 {
,类型 }?;其中 EQU 可用 “ ” 代替。???? ???? 名称为 EQU 伪指令定义的字符名称,当表达式为 32
位的常量时,可以指定表达式的数据类型,可以有以下三种类型: CODE16 、 CODE32 和 DATA?。??? ??? ??
?? 2 数据变量定义伪指令(Cont.) 数据变量定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等操
作。常见的数据变量定义伪指令有如下几种: ???(1)GBLA、GBLL 和GBLS ??? 语法格式:GBLA ( GBLL
或 GBLS ) 全局变量名???? ??? GBLA 、 GBLL 和 GBLS 伪指令用于定义全局变量,并将其初始化。其中:
???? ① GBLA用于定义一个全局的数字变量,并初始化为 0 ; ② GBLL用于定义一个全局的逻辑变量,并
初始化F(假); ③ GBLS用于定义一个全局的字符串变量,并初始化为空;2 数据变量定义伪指令(Cont.) (2)LCL
A、LCLL 和LCLS???? ??? 语法格式: LCLA ( LCLL 或 LCLS ) 局部变量名???? ??? L
CLA 、 LCLL 和 LCLS 伪指令用于定义一个 ARM 程序中的局部变量,并将其初始化。其中: ??① LCLA伪指令用于
定义一个局部的数字变量,并初始化为 0 ; ??② LCLL伪指令用于定义一个局部的逻辑变量,并初始化为 F(假); ??③ LC
LS 伪指令用于定义一个局部的字符串变量,并初始化为空; 2 数据变量定义伪指令(Cont.) (3)SETA、SETL 和SE
TS? ??? 语法格式:变量名 SETA ( SETL 或 SETS ) 表达式? ??? 伪指令 SETA 、 SETL 、
SETS 用于给一个已经定义的全局变量或局部变量赋值。 ???① SETA 伪指令用于给一个数学变量赋值; ???② SETL
伪指令用于给一个逻辑变量赋值; ???③ SETS 伪指令用于给一个字符串变量赋值; 2 数据变量定义伪指令(Cont.) (4
)RLIST???? ??? 语法格式:名称 RLIST { 寄存器列表 }? ??? RLIST 伪指令可用于对一个通用寄存器
列表定义名称,使用该伪指令定义的名称可在 ARM 指令 LDM/STM 中使用。在 LDM/STM 指令中,列表中的寄存器访问次序
为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。 ??? 3 内存分配伪指令 内存分配伪指令一般用于为特定的数据分
配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪指令有如下几种:?(1)DCB???? ?? 语法格式:??标号
DCB 表达式??? (2) DCW(或DCWU)???? ??? 语法格式:??标号 DCW (或 DCWU ) 表达式
???3 内存分配伪指令(Cont.) (3)DCD(或DCDU)???? ??? 语法格式:???标号 DCD (或 DC
DU ) 表达式?(4)DCFD(或DCFDU)???? ??? 语法格式:?标号 DCFD (或 DCFDU ) 表达式??
? (5)DCFS(或DCFSU)???? ??? 语法格式:??标号 DCFS (或 DCFSU ) 表达式3 内存分配伪指
令(Cont.) (6)DCQ(或DCQU) ??? 语法格式:??标号 DCQ (或 DCQU ) 表达式?(7) SPACE?
??? ??? 语法格式:????标号 SPACE 表达式?(8)MAP???? ??? 语法格式:??? MAP 表达式 {
,基址寄存器 }?(9)FILED? ??? 语法格式:标号 FIELD 表达式4 汇编控制伪指令 汇编控制伪指令用于控制汇编
程序的执行流程,常用的汇编控制伪指令包括以下几条: ???(1) IF、ELSE、ENDIF? ??? 语法格式:??? IF
逻辑表达式????? 指令序列 1? ELSE???? ???
指令序列 2???? ??? ENDIF???? ?????? 4
汇编控制伪指令(Cont.) (2) WHILE、WEND???? ??? 语法格式:???? ??? W
HILE 逻辑表达式 ??? 指令序列 ??? WEND ???? (3) M
EXIT? ??? 语法格式: MEXIT???? ??? MEXIT 用于从宏定义中跳转出去。 4 汇编
控制伪指令(Cont.) (4) MACRO、MEND? ??? 语法格式: ??? MACRO $ 标号 宏名
$ 参数 1 , $ 参数 2 ,…… ??? 指令序列???? ??? MEND????
??? MACRO、MEND伪指令可以将一段代码定义为一个整体,然后就可以在程序中通过宏指令多次调用该段代码。?? 5 其
他常用的伪指令?? 还有一些其他的伪指令,在汇编程序中经常会被使用,主要包括AREA、ALIGN、CODE16、CODE32、EN
TRY、END、EXPOR(或 GLOBAL)IMPORT、EXTERN、GET(或 INCLUDE )INCBIN、RN、ROU
T等。 5 其他常用的伪指令(Cont.) (1)AREA???? ??? 语法格式: AREA 段名 属性 1 ,属
性 2 ,…… ??? AREA 伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用 “ | ” 括起来,如
|1_test| 。属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。 5 其他常用的伪指令(Cont.) (2
) ALIGN??????? 语法格式:?? ALIGN { 表达式 { , 偏移量 }}? (3) CODE16、CODE32?
??? ??? 语法格式:??? CODE16 (或 CODE32 )(4) ENTRY ??? 语法格式:?ENTRY????
? …… 5 其他常用的伪指令(Cont.) (5) END???? ??? 语法格式:?? END?(6) EXPORT(或
GLOBAL) ??? 语法格式:?EXPORT 标号 {[WEAK]} (7) IMPORT ??? 语法格式: IMPORT
标号 {[WEAK]} ???5 其他常用的伪指令(Cont.) (8) EXTERN???? ??? 语法格式:? EXTE
RN 标号 {[WEAK]}(9) GET(或INCLUDE) ??? 语法格式:???GET 文件名?(10) INCBIN??
?? ??? 语法格式:INCBIN 文件名?(11) RN???? ??? 语法格式:????名称 RN 表达式?? A
RM的汇编语言结构 在ARM(Thumb)汇编语言程序中,以相对独立的指令或数据序列的程序段为单位组织程序代码。段可以分为代码段和
数据段,代码段的内容为执行代码,数据段存放代码运行时需要用到的数据。一个汇编程序至少应该有一个代码段,也可以分割为多个代码段和数据
段,多个段在程序编译链接时最终形成一个可执行的映象文件。可执行映象文件通常由以下几部分构成:??① 一个或多个代码段,代码段的属性
为只读。??② 零个或多个包含初始化数据的数据段,数据段的属性为可读写。??③ 零个或多个不包含初始化数据的数据段,数据段的属性为
可读写。ARM汇编语言的语句格式 1. 基本语句格式ARM(Thumb)汇编语言的语句格式为:{标号} {指令或伪指令} {;注释
}规则:??① 如果一条语句太长,可将其分为若干行来书写,在行的末用续行符“\”来标识下一行与本行为同一条语句。??② 每一条指令
的助记符可以全部用大写、或全部用小写,但不能在一条指令中大、小写混用。ARM汇编语言的语句格式(Cont.) 2. 汇编语言程序中
常用的符号 在汇编语言程序设计中,可以使用各种符号代替地址、变量和常量等,以增加程序的可读性。以下为符号命名的约定:??① 符号名
不应与指令或伪指令同名??② 符号在其作用范围内必须唯一。??③ 符号区分大小写,同名的大、小写符号被视为两个不同的符号。??④
自定义的符号名不能与系统保留字相同。ARM汇编语言的语句格式(Cont.) 3. 程序中的常量程序中的常量是指其值在程序的运行过
程中不能被改变的量。ARM(Thumb)汇编程序所支持的常量有逻辑常量、数字常量和字符串常量。??① 数字常量一般为32位的整数,
无符号常量取值范围为0~232-1,有符号常量取值范围为-231~231-1。??② 逻辑常量只有两种取值:真或假。??③ 字符串
常量为一个固定的字符串,一般用来提示程序运行时的信息。ARM汇编语言的语句格式(Cont.) 4. 汇编语言程序中的变量程序中的变
量是指其值在程序的运行过程中可以改变的量。??① 逻辑变量用于在程序的运行中保存逻辑值(真/假)。??② 数字变量用于在程序的运行
中保存数字值,但数字值的大小不应超出数字变量所能表示的范围。??③ 字符串变量用于在程序的运行中保存一个字符串,但字符串的长度不应
超出字符串变量所能表示的范围。ARM汇编语言的语句格式(Cont.) 5. 程序中的变量代换程序中的变量可通过代换操作取得一个常量
。代换操作符为“$”。如果“$”在数字变量前面,编译器会将该数字变量的值转换为十六进制的字符串,并将该十六进制的字符串代换“$”后
的数字变量。基于Windows下ADS的汇编语言程序结构 ADS环境下的ARM汇编语言程序结构与其它环境下的汇编语言程序结构大体相
同,整个程序也是以段为单元来组织代码。其语法规则总结如下:??① 所有标号必须在一行的顶格书写,其后不要添加“:”号;??② 所有
的指令均不能顶格写;??③ 大小写敏感(可以全部大写或全部小写,但不能大小写混合使用); ??④ 注释使用分号“;” 。基于Lin
ux下GCC的汇编语言程序结构Linux下GCC的汇编语言结构与其它环境下的汇编语言结构相似,整个程序都是以程序段为单位来组织代码
,但是在语言规则上与ADS环境下的ARM汇编语言规则有明显的区别。现将Linux下GCC的汇编语言规则总结如下:??① 所有标号必
须在一行的顶格书写,并且其后必须添加“:”号;??② 所有的指令均不能顶格写;??③ 大小写敏感(可以全部大写或全部小写,但不能大
小写混合使用); ??④ 注释使用分号“@” (注释的内容由“@” 号起到此行结束,注释可以在一行的顶格书写);ARM汇编语言程序
调试无论进行嵌入式系统软件开发还是硬件电路设计,调试永远是不可缺少的、非常重要的一个环节。通常嵌入式系统的调试方法和类型有很多种,
最为常见的包括软件模拟调试、硬件仿真器在线调试、Wiggler线缆调试和Linux环境下的gdb程序调试。ADS软件模拟环境下的程
序调试 ADS软件模拟调试是利用ARMUL.dll提供的一个软ARM内核,调试工具和待调试的嵌入式软件都在主机上运行,由主机提供一
个模拟的目标运行环境,可以进行语法和逻辑上的调试。它的优点是简单方便,不需要嵌入式目标板,软件的调试功能较强;功能有限,不能进行实
时联机调试。ADS硬件仿真器环境下的程序调试 在ADS环境下利用JTAG硬件仿真器可以实现联机调试,即在线调试嵌入式设备的Flas
h中的程序或者SDRAM中的程序。由于仿真器自成体系,调试时既可以连接目标板,也可以不连接目标板,当然仿真器的价格也相对比较贵。一
般在程序的前期开发,通常让程序只在SDRAM中调试运行,最后才下载到Flash中进行调试运行。ADS硬件仿真器环境下的程序调试(C
ont.) ARM仿真器是通过内部硬件实现PC并口协议到串行JTAG(Jiont Test Action Gruop)协议的转换。
利用高速JTAG串行扫描链,通过调试通信通道(Debug Communications Channel,DCC)连接ARM核心内嵌
的名为“Embedded-ICE”的调试逻辑,调试逻辑实时监测ARM核心的寄存器、数据总线和地址总线。ADS硬件仿真器环境下的程序
调试(Cont.) 1. Multi-ICE server 软件的安装ADS硬件仿真器环境下的程序调试(Cont.) 2.运行Mu
lti-ICE server保证硬件正确连接后,即可运行Multi-ICE server,默认情况下,server 会用自动配置来
连接目标器件。当然,可以在settings 菜单下选择配置的方式,一般选择Atuo-Configure即可。如果正确连接到一个AR
M内核的嵌入式目标板,将显示图。ADS硬件仿真器环境下的程序调试(Cont.) 3. 配置ADS以支持JTAG仿真器启动ADS的调
试器AXD后,从菜单“Option”中选择“Configure Target”,在弹出的窗口中,选择Multi-ICE,如果没有此
项,则需要将Multi-ICE驱动添加到对话框中。如图所示。ADS Wiggler调试电缆环境下的程序调试 Wiggler调试电缆
实际上可以看出就是一个简易的JTAG“仿真器”,它也支持ADS集成开发环境和在线联机调试,支持单步、全速及断点等调试功能。ADS
Wiggler调试电缆环境下的程序调试(Cont.) 1. Wiggler JTAG 调试电缆的驱动安装要使用Wiggler JT
AG 调试电缆来调试ARM 处理器,除了ADS1.2 集成开发环境外,还需要安装一个ARM 调试代理,一般使用H-JTAG 软件,
H-JTAG 软件的特点如下:① 支持ARM7/ARM9,支持自动检测和手动指定内核;② 使用RDI 接口,支持SDT2.51、A
DS1.2、REALVIEW 和IAR 集成开发环境;③ 支持2 个硬件断点或数量不限的软件断点;④ 支持ARM/Thumb 模式
;⑤ 支持Little Endian & BIG Endian 模式;⑥ 支持Semihosting 调试;⑦ 支持Wiggler
、SDT JTAG 和自定义接口。首先,用鼠标双击H-JTAG软件的安装文件H-JTAG V0.2.exe,启动H-JTAG 安装
界面,按照提示操作完成安装。ADS Wiggler调试电缆环境下的程序调试(Cont.) 2. 运行H-JATG软件接着,将Wig
gler JTAG 调试电缆一头通过并口延长线与PC机的并口连接,另一头接到嵌入式目标板的JTAG插座上。然后启动H-JTAG。H
-JTAG会自动检测ARM 内核,如果JTAG 连接正确将会在H-JTAG主窗口中显示处理器的型号.ADS Wiggler调试电缆
环境下的程序调试(Cont.) 3. 配置ADS以支持JTAG仿真器启动ADS的调试器AXD后,从菜单“Option”中选择“Co
nfigure Target”,在弹出的窗口中,添加或选择H-JTAG.dll(如图所示)。Linux环境下的gdb程序调试 Li
nux下提供了一个叫 gdb的GNU调试程序,主要用来调试C、C++等应用程序。它可以提供: ① 监视程序中变量的值;
② 设置断点以使程序在指定的代码行上暂停执行; ③ 单步执行; 语法格式: gdb gdb 基
本命令 ARM汇编语言与C语言混合编程 ARM体系结构支持C/C++以及汇编语言的混合编程,在一个完整的程序设计中,除了初始化部分
用汇编完成以外,其主要的编程任务一般都用C/C++完成。 汇编语言和C/C++的混合编程通常有以下几种方式: ① 汇
编程序中调用C程序 ② C程序中调用汇编程序 ③ C程序中内嵌汇编语句 ④ 从汇编程序中访问C程序变量基本
的ATPCS 基本的ATPCS规定了在混合编程时子程序调用的一些基本规则,主要包括寄存器的使用、堆栈的使用、参数传递和子程序结果的
返回等方面的规则。1. 寄存器的使用规则① 程序通过寄存器R0~R3来传递参数,这时这些寄存器可以记作A0~A3,被调用的子程序在
返回前无需恢复寄存器R0~R3的内容。基本的ATPCS (Cont.) ② 在子程序中,使用R4~R11来保存局部变量,这时这些寄
存器可以记作V1~V8。③ 寄存器R12用作子程序间scratch寄存器,记作IP,在子程序的连接代码段中经常会有这种使用规则。基
本的ATPCS (Cont.) ④ 寄存器R13用作数据栈指针,记做SP,在子程序中寄存器R13不能用做其他用途。⑤ 寄存器R14
用作连接寄存器,记作LR,它用于保存子程序的返回地址。⑥ 寄存器R15是程序计数器,记作PC,它不能用作其他用途。⑦ ATPCS中
的各寄存器在ARM编译器和汇编器中都是预定义的。基本的ATPCS (Cont.) 2. 堆栈的使用规则???? 栈指针通常可以指
向不同的位置,当栈指针指向栈顶元素时,称为FULL栈。当栈指针指向与栈顶元素相邻的一个元素时,称为Empty栈。 数据栈的增长方向
也可以不同,当数据栈向内存减小的地址方向增长时,称为Descending栈;反之称为Ascending栈。基本的ATPCS (Co
nt.) 3. 参数的传递规则根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子程序,这两种子程序的参数
传递规则不同的。?① 参数个数可变的子程序参数传递规则。② 参数个数固定的子程序参数传递规则。基本的ATPCS (Cont.) 4
. 子程序结果返回规则① 结果为一个32位的整数时,可通过寄存器R0返回。② 结果为一个64位整数时,可以通R0和R1返回,依此类
推。③ 结果为一个浮点数时,可以通过浮点运算部件的寄存器f0,d0或者s0来返回。④ 结果为一个复合的浮点数时,可以通过寄存器f0
-fN或者d0~dN来返回。⑤ 对于位数更多的结果,则需要通过调用内存来传递。汇编程序中调用C程序 2. C语言文件/C fil
e, called by asmfile /int cFun(int a, int b, int c){return a + b
+ c;}这里的参数传递是利用寄存器r0~r2。需要指出的是当函数的参数个数大于4时就要借助堆栈。C程序中调用汇编程序 在汇编程
序中使用EXPORT伪指令声明程序,使得本程序可以被其他的程序调用;在C语言中使用EXTERN关键词声明该汇编程序,这样就可以在C
中使用该函数了。从C的角度,并不知道该函数的实现是用C还是汇编。C程序中内嵌汇编语句在C中内嵌的汇编指令支持大部分的ARM和Thu
mb指令,不过其使用与汇编文件中的指令有些不同,存在一些限制,主要有下面几个方面:① 不能直接向PC寄存器赋值,程序跳转要使用B或
者BL指令;② 在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突;③ R12和R13可能被编译器用来存放中间编译
结果;④ 一般不要直接指定物理寄存器,而让编译器进行分配;从汇编程序中访问C程序变量在C程序中声明的全局变量可以被汇编程序通过地址
间接访问,具体访问方法如下:① 使用IMPORT伪指令声明该全局变量。② 使用LDR指令读取该全局变量的内存地址,通常该全局变量的
内存地址值存放在程序的数据缓冲区中。③ 根据该数据的类型,使用相应的LDR指令读取该全局变量的值,使用相应的STR指令修改该全局变
量的值。从汇编程序中访问C程序变量(Cont.) 各数据类型及其对应的LDR/STR指令如下:① 对于无符号的char类型的变量通过指令LDRB/STRB来读写。② 对于无符号的short类型的变量通过指令LDRH/STRH读写。③ 对于int类型的变量通过指令LDR/STR来读写。④ 对于有符号的char类型的变量通过指令LDRSB来读取。⑤ 对于有符号的char类型的变量通过指令STRB来写入。⑥ 对于有符号的short类型的变量通过指令LDRH来读取。⑦ 对于有符号的short类型的变量通过指令LDRH来写入。⑧ 对于小于8个字的结构型变量,可以通过一条LDM/STM指令来读/写整个变量。⑨ 对于结构型变量的数据成员,可以使用相应的LDR/STR指令来访问,这时必须知道该数据成员相对于结构型变量开始地址的偏移量。从汇编程序中访问C程序变量(Cont.) 下面是一个在汇编程序中访问C程序全局变量的例子。AREA global_exp, CODE, READONLYEXPORT asmsubIMPORT globv ;声明全局变量asmsubLDR r1, = globv ;将内存地址读入到R1中LDR r0, [r1] ;将数据读入到R0中ADD r0, r0, #2 STR r0, [r1] ;修改 后再将值赋予变量MOV pc, lrEND从汇编程序中访问C程序变量(Cont.) 程序中,变量globv1是在C程序中声明的全局变量,在汇编程序中首先使用IMPORT伪指令声明该变量,再将其内存地址读入到寄存器R1中,将其值读入到寄存器R0中,修改后再将寄存器R0的值赋予变量globv。
献花(0)
+1
(本文系大高老师首藏)