汇编语言编写方法及程序分析
1. 汇编语言程序的编写方法
(1) 汇编语言源程序以.asm为其扩展名。
(2) 汇编语言源程序的每一行都可以由4个部分组成,句法如下:
[标号][:] 助记符 [操作数] [;注释]
其中可用空格或TABS键隔开
标号――供本程序的其他部分或其他程序调用。标号是任选项,标号后面可以加也可以不加冒号“:”。标号必须从第一列写起,标号最多可达到32个字符(A~Z ,a~z ,0~9 ,_ ,以及$),但第1个字母不能以数字开头。引用标号时,标号的大小写必须一致。标号的值就是SPC(段程序计数器)的值。如果不用标号,则第一个字母必须为空格、分号或信号(*)。
助记符――助记符指令、汇编指令、宏指令和宏调用。作为助记符指令,一般用大写;汇编命令和宏指令,以句号“.”开始,且为小写。汇编命令可以形成常数和变量,当用它控制汇编和连接过程时,可以不占用存储空间。指令和汇编命令都不能写在第1列。
操作数――指令中的操作数或汇编命令中定义的内容。操作数之间必须用逗号“,”分开。有的指令操作无操作数,如NOP、RESET。
注释――注释从分号“;”开始,可以放在指令或汇编命令的后面,也可以放在单独的以行或数行。注释是任选项。(如果注释从第1列开始,也可以用“*”。)
(3) 常用的汇编命令如表所示。
汇编命令 |
作用 |
举例 |
.title |
紧随其后的是汇编语言程序正文 |
.title “example.asm” |
.end |
结束汇编命令 |
放在汇编语言程序的最后 |
.text |
紧随其后的是汇编语言程序正文 |
经汇编后,紧随.text后的是可执行程序代码 |
.data |
紧随其后的是已初始化数据 |
有两种数据形式:.int和.word |
.int |
.int用来设置一个或多个16位无符号整型量常数 |
table: .word 1,2,3,4 .word 6,8,4,2 |
.word |
.word 用来设置一个或多个16位符号整型量常数 |
表示在程序存储器标号为table开始的8个单元中存放初始化数据1,2,3,4,6,8,4,2 |
.bss |
.bss为未初始化变量保留存储空间 |
.bss x,4 表示在数据存储器中空出4个存储单元存放变量x1,x2,x3和x4 |
.sect |
建立包含代码和数据的自定义段 |
.sect “vectors”定义向量表,紧随其后的是复位向量和中断向量,名为vectors |
.usect |
为未初始化变量保留存储空间的自定义段 |
STACK .usect “STACK”,10h 在数据存储器中留出16个单元作为堆栈区,名为STACK |
(4) 汇编语言程序中的数据形式如表所示
形式 |
举例 |
二进制 |
1110001b或1111001B |
八进制 |
226q或572Q |
十进制 |
1234或+1234或-1234(缺省型) |
十六进制 |
|
浮点数 |
1.654e-23(仅C语言程序中能用,汇编程序中不能用) |
字符 |
‘D’ |
字符串 |
“this is a string” |
2. 程序
2.1 程序一
编程目的:本程序是试编的第一个程序,其主要目的是为了了解DSP的输入和输出方法
程序功能:求乘积之和y=a1*x1+a2*x2+a3*x3+a4*x4
.title "sample.asm"
.mmregs ;将存储映像寄存器导入列表
STACK .usect "STACK",10h ;给堆栈段分配空间
.bss a,4 ;将9个字分配给各个变量
.bss x,4
.bss y,1
PA0 .set 0
.def start
.data ;以下是分配的数据
table: .word 4,4,4,4
.word 4,4,4,4
.text ;以下是数据
start: STM #0,SWWSR ;将等待位设为0
STM #STACK+10h,SP ;设堆栈指针
STM #a,AR1 ;将AR1指向变量a
RPT #7 ;从 程序存储空间转移8个值到数据储存空间
MVPD table,*AR1+
CALL SUM ;调用SUM子程序
end: B end
SUM: STM #a,AR3 ;子程序
STM #x,AR4
RPTZ A,#3 ;求乘积之和
MAC *AR3+,*AR4+,A
STL A,@y ;将寄存器A中的低16位存入y地址 空间
PORTW @y,PA0 ;将y地址中的值输出到输出口
RET ;子程序返回
.end ;程序结束
等待位的设置:
‘C54x片内有一部件――软件可编程等待状态发生器,控制着外部总线的工作。软件可编程等待状态发生器可将外部总线周期延长多达7个周期,这样一来,’C54x就能很方便的与外部慢速器件相接口。如果外部器件要求插入7个以上的等待周期,则可以利用硬件READY先来接口。当所有的外部寻址都配置在0等待状态时,加到等待状态发生器的时钟被关断;来自内部时钟的这些通道被切断后,可以降低处理器的功耗。
软件可编程等待状态发生器的工作受到一个16位的软件等待状态寄存器(SWWSR)的控制,它时一个存储器映象寄存器,在数据空间的地址为0028h。
将程序空间和数据空间都分成两个32K 字块,I/O空间由一个64K字块组成。这5个字块空间在SWWSR中都相应的有一个3位字段,用来定义各个空间插入等待状态的数目:
15 14~12 11~9 8~6 5~3 2~0
保留/XPA(仅’C548,‘C549) |
I/O空间(64K) |
数据空间 (高32K) |
数据空间 (低32位) |
程序空间 (高32位) |
程序空间 (低32位) |
R R/W R/W R/W R/W R/W
上述SWWSR的各个3位字段规定的插入等待状态的最小数为0(不插入等待周期),最大数为7(111b)。
2.2程序二
编程目的:熟悉DSP汇编程序设计技巧,完善输出功能
程序功能:实现一8位LED灯泡由左到右循环闪烁
.title "bubble.asm"
.mmregs
STACK .usect "STACK",5h
.bss y,1
.def start
.data
PA0 .set 0
.text
start: STM #7000,SWWSR ;设等待位
STM #2,AR3 ;将辅助寄存器AR3设为2 (乘2,实现左移)
STM #6,AR1 ;将辅助寄存器AR1设为6 (左移7次)
STM #3,AR2 ;将辅助寄存器AR2设为3 (循环执行4次)
LD AR3,T ;将T(乘法寄存器)设为2
loop1: LD #1,A ;A寄存器值为1
STL A,@y ;y=1
PORTW @y,PA0 ;输出y地址内的值到输出口
STM #10000,AR4 ;将辅助寄存器AR4设为10000
loop3: RPT #10000 ;重复执行下一程序10001次
NOP ;等待
BANZ loop3,*AR4- ;循环AR4值(10000)+1次
loop2: MPY @y,A ;将y×T,其值存入A寄存器
STL A,@y ;将A内值存入y地址中
PORTW @y,PA0 ;输出y地址值到输出口
STM #10000,AR5 ;将辅助寄存器AR5设为10000
loop4: RPT #10000 ;实现第8个灯跳转到第1个灯时的时间延迟
NOP
BANZ loop4,*AR5-
BANZ loop2,*AR1-
BANZ loop1,*AR2-
end: B end
.end
数据寻址方式:
‘C54x共有7种数据寻址方式,如表所示:
寻址方式 |
用途 |
举例 |
指令含义 |
立即寻址 |
主要用于初始化 |
LD #10,A |
将立即数10传送至累加器A |
绝对寻址 |
利用16位地址寻址存储单元 |
STL A,*(y) |
将累加器A的低16位存放到变量y所在的存储单元中 |
累加器寻址 |
把累加器的内容作为地址 |
READYA x |
按累加器A作为地址读程序存储器,并存入变量x所在的数据存储器单元 |
直接寻址 |
利用数据页指针和堆栈指针寻址 |
LD @x,A |
(DP+x的低7位地址)――A |
间接寻址 |
利用辅助寄存器作为地址指针 |
LD *AR1,A |
((AR1))—-A |
存储器映象寄存器寻址 |
快速寻址存储器映象寄存器 |
LDM ST1,B |
(ST1)――B |
堆栈寻址 |
压入/弹出数据存储器和MMR(存储器映象寄存器) |
PSHM AG |
(SP)-1――SP,(AG)――TOS |
‘C54x寻址存储器有两种基本的数据形式:16位数和32位数。大多数指令能够寻址16位数,但是,只有双精度和长字指令才能寻址32位数。
在32位寻址时,先处理高有效字,然后处理低有效字。如果寻址的第1个字处在偶地址,那么第2 个字就处在下一个(较高的)地址;如果第1各字处在奇地址,那么第2个字就处在前一个(较低的)地址。
循环操作:BANZ
在程序设计时,经常需要重复执行某一段程序。利用BANZ(当辅助寄存器部位0时转移)指令执行循环技术和操作是十分方便的。如果要重复执行n次,则重复指令中应规定计数值为n-1次。
重复操作:
‘C54x有3条重复操作指令:RPT(重复下条指令)、RPTZ(累加器清0并重复下条指令)以及RPTB(块重复指令)。
重复指令RPT或 RPTZ允许重复执行紧随其后的那一条指令。如果要重复执行n次,则重复指令中应规定计数值为n-1次。
2.3 程序三
编程目的:实现DSP分时输入与输出功能
程序功能:先从I/O口读入一数据并将其存入某地址,再从该地址将数据输出到I/O口
.title "dspio.asm"
.mmregs
PA0 .set 0
PA1 .set 1
STACK .usect "STACK",10h
.bss y,1
.text
start: PORTR PA1,@y ;从I/O口读入数据并储存到y所在的地址 LD @y,A ;将y中的数据写入累加器A中(便于观察y中数值
的变化情况)
PORTW @y,PA0 将y所在地址中的数据输出到I/O口;
end: B end
.end
2.4 程序四
编程目的:实现DSP循环输入与输出功能
程序功能:令DSP反复执行从输入装置读取数据,并将数据存入某一地址,再从该地址将数据输出到输出设备
.title "dspio2.asm"
.mmregs
PA0 .set 0
PA1 .set 1
STACK .usect "STACK",10h
.bss y,1
.text
start: STM #4000,AR1
LOOP1: PORTR PA1,@y ;循环读写
LD @y,A
PORTW @y,PA0
BANZ LOOP1,*AR1
end: B end
.end
2.5 程序五
编程目的:应用DSP实现对压水堆大破口事故(LOCA)进行事故后果判断
编程背景:当始发事件大LOCA发生时,需要下列功能响应以消除或缓解事故:
(1) 停堆(RS),中止核裂变过程;
(2) 安全壳喷淋系统动作,以降低安全壳压力(COI);
(3) 向堆芯注入应急冷却水(ECI),以冷却堆芯;
(4) 安全壳再循环冷却(COR),由循环喷淋水导出安全壳内热量,控制安全壳的温度核压力;
(5) 堆芯再循环冷却(ECR),进行堆芯再循环冷却阶段。
功能事件树图如下图所示
破口 PB |
堆次临界RS |
安全壳降压COI |
堆芯应急冷却ECI |
完全壳降压COR |
堆芯再循环冷却ECR |
序列号 |
堆芯是否熔化 |
程序功能:反复从输入口读取数据(不同位分别代表执行不同的功能响应),经DSP处理后将判断结果输出到输出口,通过指示灯(不同的灯代表不同事故结果)显示出来
.title "LOCA.asm"
.mmregs
PA0 .set 0
PA1 .set 1
STACK .usect "STACK",10h
.bss y,1
.bss x,1
.def start
.data
table: .word 0,128,0,128,0,32,0,32,0,128,0 ;事故分析列表
.word 128,0,32,0,32,0,0,0,0,0
.word 4,0,4,0,0,0,0,0,4,0
.word 4,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,2,0,2,0,0,0,0,0
.word 2,0,2,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 16,0,16,0,0,0,0,0,16,0
.word 16,0,0,0,0,0,1,0,1,0
.word 0,0,0,0,1,0,1,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0,8,0
.word 8,0,0,0,0,0,8,0,8,0
.word 64,0,64,0,0,0,0,0,64,0
.word 64,0,0,0,0,0,0,0,0,0
.text
start: STM #1,AR1 ;将AR1置1
STM #table,AR2 ;将标号table的地址付给
;AR2
STM #1,AR3 ;将AR3置1
LOOP1: PORTR PA0,@y ;循环从输入口写入数据到
;y所在的地址
LD @y,B ;将y地址中的值写入B
;寄存器(便于查看y的值)
LD @AR2,A ;将table的地址写入A
ADD @y,A ;将table的地址与读入的
;数据相加,结果存入A
STL A,@AR3 ;将A的低16位存入AR3
PORTW *AR3,PA0 ;用AR3作为地址指针寻址
;并将结果输出到输出口
BANZ LOOP1,*AR1
end: B end
.end