COUNT EQU 0x30003100 定义变量COUNT的基地址 AREA Example1,CODE,READONLY声明代码段Example1为只读 ENTRY 标识程序入口
CODE32 声明32位ARM指令 START LDR R1,=COUNT 将0X30003100赋给R1 MOV R0,#0 执行R0=0
STR R0,[R1] 存储R0寄存器的数据到R1指向的存储单元 LOOP LDR R1,=COUNT 将0X30003100赋给R1
LDR R0,[R1] 将R1中的数值作为地址,取出此地址中的数据保存到R0中 ADD R0,R0,#1 执行R0=R0+1
CMP R0,#10 将R0与10进行比较
MOVHS R0,#0 若R0大于等于10,则R0=0
STR R0,[R1] 存储R0寄存器的数据到R1指向的地址单元 B LOOP 跳转到LOOP
END 汇编文件结束
二,9的8次幂
X EQU 9 初始化X为9 n EQU 8 初始化N为8
AREA Example3,CODE,READONLY 生明代码段Example3为只读 ENTRY 标识程序入口路
CODE32 声明32位ARM指令
START LDR SP,=0x30003F00 把0x30003F00 赋给SP(R13) LDR R0,=X 把9赋给R0 LDR R1,=n 把8赋给R1
BL POW 跳转到POW,并把下一条指令地址存入到R14中 HALT B HALT 等待跳转
POW STMFD SP!,{R1-R12,LR} 将R1-R12入栈,满递减堆栈 MOVS R2,R1 将R1赋给R2,并影响标志位 MOVEQ R0,#1 若Z=1,则R0=1
BEQ POW_END 若Z=1,跳转到POW_END MOV R1,R0 将R0中值赋给R1 SUB R2,R2,#1 将R2-1的只赋给R2 POW_L1 BL DO_MUL 跳转到DO-MUL,并把下一条指令地址存入R14中 SUBS R2,R2,#1 将R2-1的值赋给R2,并影响标志位 BNE POW_L1 若Z=0,跳转到POW_L1
POW_END LDMFD SP!,{R1-R12,PC} 数据出栈,存入到R1-R12,PC中 DO_MUL MUL R0,R1,R0 把R1*R0的值赋给R0 MOV PC,LR LR中的值赋给PC END 汇编结束
三:从一一直加到一百
程序清单(一) C 语言实验参考程序
#define uint8 unsigned char 定义一个无符号字符常量uint8 #define uint32 unsigned int 定义一个无符号整型常量unint32
#define N 100 定义一个常量N=100(宏定义,100用N代替) uint32 sum定义sum为无符号整型常量(声明一个unsigned int型的变量sum) void Main(void) 主函数
{uint32 i定义无符号整型常量i(声明一个unsigned int型的变量i) sum=0sum初始值为0
for(i=0i<=Ni++) i在N内自增加1(i从0开始,i<=N时循环成立) {sum+=i} 把sum+i赋给sum while(1)为真循环 }
程序清单(二) 简单的启动代码
IMPORT |Image$$RO$$Limit | R0输出段存储区域界线 IMPORT |Image$$RW$$Base | RW输出段运行时起始地址 IMPORT |Image$$ZI$$Base | ZI输出段运行时起始地址 IMPORT |Image$$ZI$$Limit | ZI输出段存储区域界线 IMPORT Main 主函数
AREA Start,CODE,READONLY 声明代码段start,为只读 ENTRY 程序入口
CODE32 声明32位ARM指令 Reset LDR SP,=0x40003f00 将0x40003f00赋给SP
LDR R0,=|Image$$RO$$Limit| 将R0输出段存储区域界线赋给R0 LDR R1,=|Image$$RW$$Base | 将RW输出段运行时起始地址赋给R1 LDR R3,=|Image$$ZI$$Base | 将ZI输出段运行时起始地址赋给R3 CMP R0,R1 比较R0和R1,相等Z=1,反之Z=0 BEQ LOOP1 若Z=1,则跳到LOOP1
LOOP0 CMP R1,R3 比较R1和R3,若R1<r3,c=0
LDRCC R2,[R0],#4 若C=0,读取R0地址单元内容并且存入R2,且R0=R0+4 STRCC R2,[R1],#4 若C=0,读取R2中的数据存入R1,且R1=R1+4 BCC LOOP0 若C=0,跳转到LOOP0
LOOP1 LDR R1,=|Image$$ZI$$Limit| 将ZI输出段存储区域赋给R1 MOV R2,#0 把0赋给R2
LOOP2 CMP R3,R1 比较R1和R3,若R1<r3,c=0 strcc="" r2,[r3],#4="" 若c="0,将R2中数据保存到内存单元R3中,且R3=R3+4" bcc="" loop2="" b="" main="" 跳转到主程序="" end="" 汇编结束=""
四、程序清单(一) C 语言调用汇编的参考程序
#define uint8 unsigned char 定义一个无符号字符常量uint8 #define uint32 unsigned int 定义一个无符号整型常量.uint32
extern uint32 Add(uint32 x,uint32 y)//声明子程序Add为一个无符号整型常量,它为2个无符号整型常量x,y的和
uint32 sum定义sum为无符号整型常量 void Main(void) 无返回主程序
{sum=Add(555,168)sum等于555+168 while(1)为真循环 }
程序清单(二) 汇编加法函数程序
EXPORT Add 声明子程序Add方便调用 AREA Start,CODE,READONLY 声明代码段start,为只读 ENTRY 程序入口
CODE32 声明32位ARM指令
Add ADD R0,R0,R1 将R0+R1值赋给R0 MOV PC,LR 将LR值赋给PC
在ARM汇编语言程序里,有一些特殊指令助记符,这些助记符与指令系统的助记符不同,没有相对应的 *** 作码,通常称这些特殊指令助记符为伪指令,他们所完成的 *** 作称为伪 *** 作。伪指令在源程序中的作用是为完成汇编程序作各种准备工作的,这些伪指令仅在汇编过程中起作用,一旦汇编结束,伪指令的使命就完成。在ARM的汇编程序中,有如下几种伪指令:符号定义伪指令、数据定义伪指令、汇编控制伪指令、宏指令以及其他伪指令。
4.1.1 符号定义(Symbol Definition)伪指令
符号定义伪指令用于定义ARM汇编程序中的变量、对变量赋值以及定义寄存器的别名等 *** 作。常见的符号定义伪指令有如下几种:
— 用于定义全局变量的GBLA、GBLL和GBLS。
— 用于定义局部变量的LCLA、LCLL和LCLS。
— 用于对变量赋值的SETA、SETL、SETS。
— 为通用寄存器列表定义名称的RLIST。
1、 GBLA、GBLL和GBLS
语法格式:
GBLA(GBLL或GBLS) 全局变量名
GBLA、GBLL和GBLS伪指令用于定义一个ARM程序中的全局变量,并将其初始化。其中:
GBLA伪指令用于定义一个全局的数字变量,并初始化为0;
GBLL伪指令用于定义一个全局的逻辑变量,并初始化为F(假);
GBLS伪指令用于定义一个全局的字符串变量,并初始化为空;
由于以上三条伪指令用于定义全局变量,因此在整个程序范围内变量名必须唯一。
使用示例:
GBLA Test1 ;定义一个全局的数字变量,变量名为Test1
Test1 SETA 0xaa ;将该变量赋值为0xaa
GBLL Test2 ;定义一个全局的逻辑变量,变量名为Test2
Test2 SETL {TRUE} ;将该变量赋值为真
GBLS Test3 ;定义一个全局的字符串变量,变量名为Test3
Test3 SETS “Testing” ;将该变量赋值为“Testing”
2、 LCLA、LCLL和LCLS
语法格式:
LCLA(LCLL或LCLS) 局部变量名
LCLA、LCLL和LCLS伪指令用于定义一个ARM程序中的局部变量,并将其初始化。其中:
LCLA伪指令用于定义一个局部的数字变量,并初始化为0;
LCLL伪指令用于定义一个局部的逻辑变量,并初始化为F(假);
LCLS伪指令用于定义一个局部的字符串变量,并初始化为空;
以上三条伪指令用于声明局部变量,在其作用范围内变量名必须唯一。
使用示例:
LCLA Test4 ;声明一个局部的数字变量,变量名为Test4
Test3 SETA 0xaa ;将该变量赋值为0xaa
LCLL Test5 ;声明一个局部的逻辑变量,变量名为Test5
Test4 SETL {TRUE} ;将该变量赋值为真
LCLS Test6 ;定义一个局部的字符串变量,变量名为Test6
Test6 SETS “Testing” ;将该变量赋值为“Testing”
3、 SETA、SETL和SETS
语法格式:
变量名 SETA(SETL或SETS) 表达式
伪指令SETA、SETL、SETS用于给一个已经定义的全局变量或局部变量赋值。
SETA伪指令用于给一个数学变量赋值;
SETL伪指令用于给一个逻辑变量赋值;
SETS伪指令用于给一个字符串变量赋值;
其中,变量名为已经定义过的全局变量或局部变量,表达式为将要赋给变量的值。
使用示例:
LCLA Test3 ;声明一个局部的数字变量,变量名为Test3
Test3 SETA 0xaa ;将该变量赋值为0xaa
LCLL Test4 ;声明一个局部的逻辑变量,变量名为Test4
Test4 SETL {TRUE} ;将该变量赋值为真
4、 RLIST
语法格式:
名称 RLIST {寄存器列表}
RLIST伪指令可用于对一个通用寄存器列表定义名称,使用该伪指令定义的名称可在ARM指令LDM/STM中使用。在LDM/STM指令中,列表中的寄存器访问次序为根据寄存器的编号由低到高,而与列表中的寄存器排列次序无关。
使用示例:
RegList R www.hbbz08.com LIST {R0-R5,R8,R10} ;将寄存器列表名称定义为RegList,可在ARM指令LDM/STM中通过该名称访问寄存器列表。
4.1.2 数据定义(Data Definition)伪指令
数据定义伪指令一般用于为特定的数据分配存储单元,同时可完成已分配存储单元的初始化。常见的数据定义伪指令有如下几种:
— DCB 用于分配一片连续的字节存储单元并用指定的数据初始化。
— DCW(DCWU) 用于分配一片连续的半字存储单元并用指定的数据初始化。
— DCD(DCDU) 用于分配一片连续的字存储单元并用指定的数据初始化。
— DCFD(DCFDU)用于为双精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
— DCFS(DCFSU) 用于为单精度的浮点数分配一片连续的字存储单元并用指定的数据初始化。
— DCQ(DCQU) 用于分配一片以8字节为单位的连续的存储单元并用指定的数据初始化。
— SPACE 用于分配一片连续的存储单元
— MAP 用于定义一个结构化的内存表首地址
— FIELD 用于定义一个结构化的内存表的数据域
1、 DCB
语法格式:
标号 DCB 表达式
DCB伪指令用于分配一片连续的字节存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为0~255的数字或字符串。DCB也可用“=”代替。
使用示例:
Str DCB “This is a test!” ;分配一片连续的字节存储单元并初始化。
2、 DCW(或DCWU)
语法格式:
标号 DCW(或DCWU) 表达式
DCW(或DCWU)伪指令用于分配一片连续的半字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。。
用DCW分配的字存储单元是半字对齐的,而用DCWU分配的字存储单元并不严格半字对齐。
使用示例:
DataTest DCW 1,2,3 ;分配一片连续的半字存储单元并初始化。
3、 DCD(或DCDU)
语法格式:
标号 DCD(或DCDU) 表达式
DCD(或DCDU)伪指令用于分配一片连续的字存储单元并用伪指令中指定的表达式初始化。其中,表达式可以为程序标号或数字表达式。DCD也可用“&”代替。
用DCD分配的字存储单元是字对齐的,而用DCDU分配的字存储单元并不严格字对齐。
使用示例:
DataTest DCD 4,5,6 ;分配一片连续的字存储单元并初始化。
4、 DCFD(或DCFDU)
语法格式:
标号 DCFD(或DCFDU) 表达式
DCFD(或DCFDU)伪指令用于为双精度的浮点数分配一片连续的字存储单元并用伪指令中指定的表达式初始化。每个双精度的浮点数占据两个字单元。
用DCFD分配的字存储单元是字对齐的,而用DCFDU分配的字存储单元并不严格字对齐。
使用示例:
FDataTest DCFD 2E115,-5E7 ;分配一片连续的字存储单元并初始化为指定的双精度数。
5、 DCFS(或DCFSU)
语法格式:
标号 DCFS(或DCFSU) 表达式
DCFS(或DCFSU)伪指令用于为单精度的浮点数分配一片连续的字存储单元并用伪指令中指定的表达式初始化。每个单精度的浮点数占据一个字单元。
用DCFS分配的字存储单元是字对齐的,而用DCFSU分配的字存储单元并不严格字对齐。
使用示例:
FDataTest DCFS 2E5,-5E-7 ;分配一片连续的字存储单元并初始化为指定的单精度数。
6、 DCQ(或DCQU)
语法格式:
标号 DCQ(或DCQU) 表达式
DCQ(或DCQU)伪指令用于分配一片以8个字节为单位的连续存储区域并用伪指令中指定的表达式初始化。
用DCQ分配的存储单元是字对齐的,而用DCQU分配的存储单元并不严格字对齐。
使用示例:
DataTest DCQ 100 ;分配一片连续的存储单元并初始化为指定的值。
7、 SPACE
语法格式:
标号 SPACE 表达式
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)