第4章汇编语言程序设计20131020

Report
第4章 汇编语言程序设计
本章结合C54x的软件开发过程,介绍
DSP所采用的COFF目标文件格式、结构
和规范。介绍汇编语言的重要组成部分:
伪指令Assembler directives和宏指令
Macro directives。讨论建立汇编语言程
序并产生可执行文件的设计要求。指出汇
编程序设计中的一些关键问题,并通过实
例介绍设计的方法和技巧。
参考:TMS320C54x Assembly Language Tools
User’s Guide.pdf, SPRU102F,2002年,TI官网
参考:TMS320C54x Code Composer Studio
Tutorial.pdf,spru327c,2000,TI官网
第4章 汇编语言程序设计
目录:
• 4.1 C54x的软件开发过程
• 4.2 公共目标文件格式COFF
• 4.3 汇编器的伪指令
• 4.4 C54x汇编语言的有关知识
• 4.5 汇编语言程序设计
第4章 汇编语言程序设计
• 4.1 C54x的软件开发过程
提供2种编程语言:汇编语言
C/C++语言
对于完成一般功能的代码,这两种语言都可使
用,但对于一些运算量很大的关键代码,最好采
用汇编语言来完成,以提高程序的运算效率。
C54x的软件开发过程可以分为文本编辑、编译、
汇编和连接这样四个基本步骤,如图4-1所示。
第4章 汇编语言程序设计
第4章 汇编语言程序设计
 C54x的软件开发需要借助于TI公司提供的软件开
发工具:编译器、汇编器和连接器,另外还有一
些辅助的软件包,如归档器、列表器和代码转换
器等。

这些软件开发工具都被集成在CCS(Code
Composer Studio)开发环境中。将在第6章详细介
绍CCS的组成及其使用方法
4.2 公共目标文件格式COFF
COFF: common object file format
汇编器和链接器生成的目标文件,是一个可以由
C54x器件执行的文件。这些目标文件的格式称之
为公共目标文件格式(COFF)。
采用这种文件格式的优点是:
将指令和数据按照段的概念进行组织和存
储,这使得程序的可读性大大增强,更容易编写
程序,更便于进行程序的移植,更利于进行模块
化的程序设计,为管理代码段及系统存储器提供
了灵活的方法和手段。
第4章 汇编语言程序设计
COFF文件有3种类型:COFF0、COFF1、COFF2
每种类型的COFF文件,其标题格式都有所不同,但
数据部分是相同的。
链接器能够读/写所有类型的COFF文件,默认时链
接器生成的是COFF2文件,采用-v n链接选项可以
选择不同类型的COFF文件。
第4章 汇编语言程序设计
4.2.1分段结构
所谓“段”就是在存储器映像中占据连续空间的一
段独立的代码或数据。每个目标文件都分成若干段。
COFF目标文件包含以下三个默认的段:

.text 段:通常内含可执行代码;

.data段:通常内含已初始化数据;

.bss段:是为没有初始化的数据保留空间的。
COFF目标文件的段又可分为两大基本类型:已初
始化段和未初始化段。
第4章 汇编语言程序设计
 Section( “段”)概念:一块连续的储存空间,可
存放程序或数据
 在编程时,“段”没有绝对定位,每个“段”都认为
是从0地址开始的一块连续的储存空间,而无需关心这
些“段”究竟定位在系统的哪些地方。
 优点:便于程序的模块化编程;便于工程化管理:可
将软件开发人员和硬件开发人员基本上分离开。
 重定位:由于所有的“段”都是从0地址开始,所以程
序编译完成后是无法运行的,要让程序正确运行,必
须对“段”进行重新定位,这个工作由链接器完成。
 .cmd文件:MEMORY命令描述系统硬件资源,SECTIONS
命令描述软件人员程序中用到的“段”如何定位到恰
当的硬件资源上。
第4章 汇编语言程序设计
1.已初始化段
包含程序代码、常数表格和数据。每个段都可以独
立的进行重定位,且可访问在其它段中定义的符号。
已初始化段的值是不可修改的,因而一般将它们建
立在程序存储器中。
主要有:
.text段——已初始化段;
.data段——已初始化段;
.sect段——已初始化段,由汇编器伪指令建立
的自定义段。
第4章 汇编语言程序设计
2.未初始化段
是为变量在数据存储器中保留空间的。它们在目
标文件中没有实际内容,只是保留出空间,在运
行程序时再利用这些空间去建立和存储变量。未
初始化段一般应建立在片内或片外RAM中。
•
由这些段定义的空间仅作为临时存储空间,在
程序运行时,可以利用这些存储空间存放变量。
•
未初始化段分为默认的和命名的两种,分别由
汇编器伪指令.bss和.usect产生。.
第4章 汇编语言程序设计
One of the linker’s functions is to relocate sections into
the target memory map;this function is called allocation.
目标文件中的段与目标存储器之间的关系:
目标文件
目标存储器
.bss
RAM
.data
E2PROM
.text
ROM
第4章 汇编语言程序设计
3. 段定义伪指令
汇编器对段的处理是通过段伪指令来区别各个段的,
并将段名相同的语句汇编在一起。
汇编器有5条伪指令可识别汇编语言程序的各个部分:
● .bss
● .usect
● .text
● .data
● .sect
——定义未初始化段
——定义未初始化段
——定义已初始化段
——定义已初始化段
——定义已初始化段
第4章 汇编语言程序设计
• 定义已初始化段的伪指令
.text
[段起点]
.data
[段起点]
.sect
“段名”[,段起点]
段起点——是任选项。
若选用,它为段程序计数器SPC定义一个起始值。
若默认,则SPC从0开始。
定义未初始化段的伪指令
(1) .bss伪指令: 用于在bss段中保留若干个空间。
格式:.bss 符号, 字数 [, [块标记][, 定位对齐标记]]
符号—对应于保留的存储空间第一个字的变量名称。
字数—表示在bss段或标有名字的段中保留若干个存
储单元。
块标记—若非零值,则分配的字数空间连续,除非大
于一页,否则不跨页。
定位标记—表明字的对齐方式(C54x偶地址对齐)
 每调用一次.bss伪指令,汇编器在相应的段保留更
多的空间。
第4章 汇编语言程序设计
• 定义未初始化段的伪指令
(2) .usect伪指令
用于为指定的命名段保留若干个空间。
格式: 标号 .usect “段名”,字数 [, [块标记][, 定位标记]]
建立一个自定义段但是没有初始化的段,在自
定义的段中保留空间。
每调用一次.usect伪指令,汇编器在指定的命
名段保留更多的空间。
第4章 汇编语言程序设计
• 例4-1:段定义程序举例。
.text
.word 1,2,3,4,5,6,7,8
.data
.word 9,10,11,12
.word 13,14
.word 15,16
.sect “var1”
.word 17,18
.bss x1,19 ;为.bss段保留19个字单元空间。
y1 .usect “var2”, 40; 为var2段保留40个单元空间。
• 例4-1:段定义程序举例。
程序建立了5个段,情况如下:
.text
.text段:8个16位字1~8。
.word 1,2,3,4,5,6,7,8
.data段:8个16位字9~16。
.data
.word 9,10,11,12
Var1段:2个16位字17,18。
.word 13,14
.bss段:保留19个字的连续空间, .word 15,16
第一个单 元的标号是x1。
.sect “var1”
.word 17,18
Var2段:保留40个字的连续空
.bss x1,19 ;
间,第一个单元的标号是y1。
y1 .usect “var2”, 40;
第4章 汇编语言程序设计
4.2.2 汇编器对段的建立
 当汇编器遇到.text或.data或.sect命令时,将停止
对当前段的汇编(相当于一条结束当前段汇编的命
令),然后将紧接着的程序代码或数据汇编到指定
的段中,直到再遇到另一条.text、.data或.sect命
令为止。
 当汇编器遇到.bss或.usect命令时,并不结束当前
段的汇编,只是暂时从当前段脱离出来,并开始对
新的段(.bss或.usect)进行汇编,结束后仍在离开
时的段。(见例4-2)
第4章 汇编语言程序设计
4.2.2 汇编器对段的建立
段程序计数器SPC
汇编器为每个段都安排了一个单独的程序计数
器称之为段程序计数器SPC。
SPC表示在程序代码或数据段内当前的地址。
开始时汇编器将每个SPC置0。当汇编器将程序代
码或数据加到段内时,增加相应的SPC值。若再
继续对某个段汇编,则相应的SPC就在先前的数
值上继续增加。
• 例4-2 段定义应用举例
汇编语言源程序:
;初始化数据段
.data
;3组数据放入.data段
coeff .word 011h,022h,033h
;在.bss段保留10个单元
.bss buffer,10
;.bss后0123h仍然在.data段
prt .word 0123h
;初始化文本段
.text
;1字指令(DP直接寻址)
add: LD 0Fh,A
;2字指令
Aloop: SUB #1,A
;2字指令
BC aloop,AGEQ
;初始化数据段
.data
ivals .word 0AAh,0BBh,0CCh ;3组数据放入.data段
汇编语言源程序:
var2 .usect “newvars”, 1 ;建立newvars命名段,保留1个单元
inbuf .usect “newvars”, 7
;初始化文本段
.text
mpy: LD
;在newvars段保留7个单元
0Ah,B
Mloop: MPY #0Ah,B
;1字指令(DP直接寻址)
;2字指令
BC mloop,BNOV ;2字指令
.sect “vectors”
.word 011h,033h
;建立vectors命名段
;2组数据放入vectors命名段
第4章 汇编语言程序设计
汇编语言源程序经过汇编后,共建立了5个段:
.text段——文本段,段内有10个字可执行的程序代码
.data段——已初始化的数据段,段内有7个字的数据
vectors段——用.sect命令生成的命名段,段内有2个字
的初始化数据
.bss段——未初始化的数据段,在存储器中为变量保留
10个存储单元
newvars段——用.usect命令建立的命名段,为变量保
留8个存储单元
例4-2 经汇编后,得列表文件(部分):
源程序 段程序 目标
的行号 计数器 代码
2
3
4
5
6
7
8
9
10
11
12
13
14
汇编语言
源程序
**********************************
** 汇编一个初始化表到.data段 **
**********************************
0000
0000
0001
0002
0011
0022
0033
coeff
.data
.word 011h,022h,033h
**********************************
** 在.bss段中为变量保留空间 **
**********************************
.bss
0000
buffer,10
**********************************
** .bss结束后仍然在.data 段中
**********************************
0003
0123
prt
.word
0123h
**
源程序 段程序 目标
的行号 计数器 代码
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
汇编语言
源程序
**********************************
** 汇编代码到.text段
**
**********************************
0000
0000
0001
0002
0003
0004
.text
100f add:
LD
f010 aloop: SUB
0004
0004
0005
0006
.data
.word
0000
0001
0001
f842
0001’
00aa
00bb
00cc
BC
0Fh,A ;DP直接寻址
#1, A
aloop,AGEQ
(’ : relocatable internal reference)
**********************************
** 汇编另一个初始化表到.data段
**********************************
ivals
0AAh,0BBh,0CCh
**********************************
** 为更多的变量定义另一个段
**********************************
var2
inbuf
.usect “newvars”,1
.usect “newvars”,7
**
例4-2 经汇编后,得列表文件(部分):
32
33
34
35
36
37
38
39
40
41
42
43
****************************************
**
汇编更多代码到.text段
**
****************************************
0005
0005
0006
0007
0008
0009
.text
LD
MPY
110a mpy:
0Ah,B
f166 mloop
#0Ah,B
000a
f868
BC
mloop,BNOV
0006’ (’ : relocatable internal reference)
****************************************
为中断向量.vectors定义一个自定义段
****************************************
0000
0000
0001
0011
0033
源程序 段程序 目标
的行号 计数器 代码
.sect
.word
“vectors”
011h,033h
汇编语言
源程序
例4-2 经汇编后,共建立了5个段:
行号SPC 目标
代码
2
3
4
5
6
6
6
7
8
9
10
11
12
13
14
0000
0000
0001
0002
0000
0003
0011
0022
0033
行号 目标代码 段名
*******************************
** 汇编一个初始化表到.data段 **
*******************************
.data
coeff .word
011h,022h,033h
6
6
******************************* 6
** 在.bss段中为变量保留空间 ** 14
*******************************
.bss
buffer,10
*******************************
**
仍然在.data 段中
**
******************************* 10
0123 prt
.word
0123h
100f
f010
0001
f842
0001
110a
f166
000a
F868
0006
0011
0011
0022
0022
0033
0123
0033
00aa
0123
00bb
.text
.data
00cc
0011
0033
vectors
没有数据 .bss
保留10个字
没有数据
保留8个字
newvars
第4章 汇编语言程序设计
目标
行号SPC
代码 ******************************** 行号 目标代码
15
16
**
汇编代码到.text段
**
17
********************************
18 0000
.text
19 0000 100f add:
LD
0Fh,A
20 0001 f010 aloop: SUB
#1, A
0002 0001
21 0003 f842
BC
aloop,AGEQ
0004 0001’
(’ : relocatable internal reference)
22
**********************************
23
** 汇编另一个初始化表到.data 段 **
24
**********************************
25 0004
.data
26 0004 00aa ivals
.word
0AAh,0BBh,0CCh
0005 00bb
0006 00cc
27
********************************
28
** 为更多的变量定义另一个段 **
29
********************************
30 0000
var2
.usect “newvars”,1
31 0001
inbuf
.usect “newvars”,7
段名
19
20
20
21
21
100f
f010
0001
f842
0001’
110a
f166
000a
F868
0006‘
.text
6
6
6
14
26
26
26
0011
0022
0033
0123
00aa
00bb
00cc
.data
.data
0011
0033
10
没有数据
保留10个字
30 保留1个字
没有数据
31 保留10个字
保留7个字
.bss
newvars
第4章 汇编语言程序设计
行号SPC 目标
代码
32
33
34
35
36
37
行号 目标代码 段名
*********************************
**
汇编更多代码到.text段
**
*********************************
.text
mpy:
LD
0Ah,B
mloop
MPY
#0Ah,B
0005
0005 110a
0006 f166
0007 000a
38 0008 f868
BC
mloop,BNOV
0009 0006’ (’ : relocatable internal reference)
39
****************************************
40
** 为中断向量.vectors定义一个自定义段 **
41
****************************************
42 0000
.sect
“vectors”
43 0000 0011
.word
011h,033h
0001 0033
19
20
20
21
21
36
37
37
38
38
100f
f010
0001
f842
0001’
110a
f166
000a
F868
f868
0006
0006’
.text
.text
6
6
6
14
26
26
26
0011
0022
0033
0123
00aa
00bb
00cc
.data
43
43
0044
0011
0088
0033
vectors
10
没有数据
保留10个字
30 没有数据
31 保留8个字
.bss
newvars
第4章 汇编语言程序设计
4.2.3 连接器对段的处理
链接器是开发’C54x器件必不可少的开发工具之
一,连接器对段的处理主要完成两个功能:
 把1个或多个目标文件(文件名.obj)连接起来,
产生可执行的COFF输出文件(文件名.out)。
 按照目标系统的需要配置存储器,并将符号和段
重新定位,确定输出文件的存储器地址。
第4章 汇编语言程序设计
定位(Allocation): 连接器将.text、.data、.bss等
段存放到硬件系统的存储空间中去,这就是定位。
连接器有两种定位的方法:
 缺省定位,是指连接器对各段的定位是固定不变的
方式;
 存储器映像定位,在连接前,使用连接器的伪指令
MEMORY和SECTIONS等编写一个命令文件,定义出存
储区域,然后,由连接器去进行存储区的映像定位。
第4章 汇编语言程序设计
如如如如如如如
1. 存储器映射定位
lnk500 a.obj b.obj -m prog.map -o prog.out
如如如如如如如如如如
用户编写的命令文件由下列4部分组成:
a.obj
1)输入文件名,用来指定目标文件、归档库文件或
b.obj
其它命令文件。-m prog.map
-o prog.out
2)连接器选项。这些选项可以编写在命令文件中,
也可以使用CCS的选项或命令行实现。
3)连接器的伪指令MEMORY和SECTIONS。
MEMORY指出目标存储器的配置;SECTIONS控
制段的构成及其地址的分配。
4)赋值说明,用来给全局符号定义和赋值。
第4章 汇编语言程序设计
2. 连接器的两个主要伪指令

MEMORY伪指令——用来定义目标系统的
存储器配置空间,包括对存储器各部分命名,以
及规定它们的起始地址和长度。

SECTIONS伪指令——用来指定链接器将输
入段组合成输出段方式,以及输出段在存储器中
的位置,也可用于指定子段。
若未使用伪指令,则连接器将使用目标处理
器默认的方法将段放入存储空间。
第4章 汇编语言程序设计
2. 连接器的两个主要伪指令
1)MEMORY命令
MEMORY用来定义目标系统的存储器。它的一
般语法如下:
MEMORY
PAGE 0 : PROG: origin = 0x0080, length = 0xFF00
{
PAGE 0 : name 1 [(attr)] : origin = constant ,
length = constant;
PAGE n : name n [(attr)] : origin = constant ,
length = constant;
} PAGE 1 : DATA: origin = 0x0080, length = 0xFF80
2. 连接器的两个主要伪指令
2)SECTIONS命令
SECTIONS用来告诉连接器怎样组合输入段以及
在存储器的何处存放输出段。在MEMORY指定了
一种存储模式后,就应使用SECTIONS去定位。
(An output section is a section in the output file.)
SECTIONS的一般语法如下: .text: PAGE = 0
.data: PAGE = 0
SECTIONS
.bss: PAGE = 1
{
name : [property, property, property,...]
name : [property, property, property,...]
name : [property, property, property,...]
}
第4章 汇编语言程序设计
 name定义一个输出文件中的输出段名,该名称不能
任意指定,而是在汇编器中已经指定的段名。
 property定义段的内容以及指明它是怎样被分配的。
 property主要有下列几种:
☆ load 定义该段装载至某存储区域
☆ run 定义该段的运行存储器区域
☆ input sections指出构成输出段的输入段
☆ Section type段的类型,定义特殊段的标志
☆ Fill value用来为没有初始化的空单元填充数值
例4-3 命令文件举例
a.obj b.obj c.obj
/* Input filenames */
-0 prog.out -m prog.map
/* Options */
MEMORY
/* MEMORY directive */
{ ROM:
origin = 01000h
length = 0100h
PAGE 1:
RAM:
origin = 100h
length = 0100h
}
SECTIONS
/* SECTIONS directive */
{
.text: > ROM
.data: > ROM
.bss: > RAM
}
第4章 汇编语言程序设计
3. 缺省定位(默认定位)
链接器可对多个目标文件进行链接。若链接文件
中不使用MEMORY和SECTIONS命令,则为默认方式。
若采用默认链接,链接器将对多个目标文件中的
各个段进行组合,形成各自的对应段,并将各个段配
置到所指定的存储器中,形成可执行的目标模块。
在默认的方式下,链接器将从存储器的0080h开
始,对组合后的各段进行存储器配置。
第4章 汇编语言程序设计
例4-4 TMS320C54x的缺省定位
MEMORY
{
PAGE 0: PROG: origin=0x0080, length=0xFF00
PAGE 1: DATA: origin=0x0080, length=0xFF80
}
SECTIONS
{
.text: PAGE = 0
.data: PAGE = 0
.cinit: PAGE = 0 ;仅用于C标志选项
.bss: PAGE = 1
}
第4章 汇编语言程序设计
在这种缺省定位方式下,默认的存储器分配:
① 将所有.text段组合在一起,形成一个.text
段,并分配到程序存储器中;
② 将多个目标文件中的.data段组合在一起,
分配到紧接着.text段的程序存储空间中;
③ 将.bss段组合,配置到数据存储器中;
④ 自命名段。初始化的命名段按顺序分配到紧
随.data段的程序存储器,而未初始化命名段将被配
置到紧随.bss段的数据存储器中。
第4章 汇编语言程序设计
程序存储器
.text1
.text .text2
.data1
.data .data2
table_1
table
table_2
FFT
FFT
没有使用
File1.obj
.text1
.data1
.bss1
table_1
(初始化的命名段)
u_vars1
(未初始化的命名段)
File2.obj
.text2
.data2
.bss2
table_2
(初始化的命名段)
没有配置
u_vars2
(未初始化的命名段)
FFT
(初始化的命名段)
数据存储器
没有配置
.bss1
.bss2
u_vars1
u_vars2
没有使用
.bss
u_vars1
4.3 汇编器的伪指令
•
汇编器的伪指令仅在汇编的过程中起作用,它们
为汇编器提供一些控制和管理的信息及功能,但并
不产生目标代码。
.text:
.data:
汇编器伪指令可完成以下工作:
.word
 将代码和数据汇编进指定的段
.bss:
 为未初始化的变量在存储器中保留空间
 初始化存储器(.word,.byte, .long .... )
 控制清单文件是否产生
 汇编条件代码块
 定义全局变量
 为汇编器指定从中可以获得宏的库
 考察符号调试信息
第4章 汇编语言程序设计
下面主要介绍以下几类汇编伪指令:
⑴ 段定义伪指令
如.bss、.data、.sect、.text、.usect等。
⑵ 对常数(数据和存储器)进行初始化的伪指令
如.bes、.byte、.field、.float、.int、.long、
.space、.string、.pstring、.xfloat、.xlong、
.word等。
第4章 汇编语言程序设计
⑶ 调整SPC的指令
如.align等。
⑷ 格式化输出清单文件的伪指令
如.drlist、.drnolist等。
⑸ 引用其他文件的伪指令
如.copy、.def、.global、.include、.mlib、
.ref等。
(6) 定义宏的伪指令
如.macro等
第4章 汇编语言程序设计
(7) 条件汇编伪指令
如.break、.else、.elseif、.endif、.endloop、
.if、.loop等。
(8)汇编时间符号伪指令
如.asg、.endstruct、.equ、.eval、.label、
.set、.sruct等。
(9)混合伪指令
如.algebraic、.emsg、.end、.mmregs、.mmsg、
.newblock、.sblock、.version、.vmsg等。
第4章 汇编语言程序设计
1.段定义伪指令
段定义伪指令为汇编器提供分段信息。
助记符及语法格式
.bss symbol, size in words
[,blocking] [, alignment]
说
明
为未初始化的数据段.bss保
留存储空间。
.data
指定.data后面的代码为数据
段,通常包含初始化的数据。
.sect “section name”
.text
symbol .usect “section name”, size
in words [,blocking] [,alignment
flag]
设置自定义已初始化段
指定.text后面的代码为文本
段,通常包含可执行的代码。
为未初始化的命名段保留空
间。类似.bss伪指令,但允
许保留与.bss段不同的空间。
2.初始化常数的伪指令
用于为当前的段汇编常数值。
助记符及语法格式
说
明
初始化当前段里的一个或多个连续字。每
.byte value [,…, value] 个值的宽度被限制为8位。即把8位的值放
入当前段的连续字。
初始化当前段里的一个或多个连续字。每
.char value [,…, value] 个值的宽度被限制为8位。即把8位的值放
入当前段的连续字。
初始化一个可变长度的域。将单个值放入
.field value [,size in bits]
当前字的指定位域中。
初始化一个或多个IEEE的单精度(32位) 浮
.float value [,…, value]
点数.
初始化一个或多个IEEE的单精度(32位) 浮
.xfloat value [,…, value] 点数, 并将它保存在当前段的两个连续的
字中。不自动对准最接近的长字边界。
2.初始化常数的伪指令
助记符及语法格式
.int value [,…,value]
说
明
初始化一个或多个16位整数。即把16
位的值放到当前段的连续的字中。
.short value [,…,value]
初始化一个或多个16位整数。
.word value [,…,value]
初始化一个或多个16位整数。
初始化一个或多个双精度(32位) 浮点数。
即计算浮点数的单精度(32位) 浮点表示,
.double value [,…,value]
并将它存储在当前段的2个连续的字中。
该伪指令自动对准长字边界。
.long value [,…,value]
初始化一个或多个32位整数。即把32
位的值放到当前段的2个连续的字中。
.string “string [,…,
“string”]”
初始化一个或多个字符串。把8位字
符从一个或多个字符串放进当前段。
【例4.5】比较.byte,.int,.long,.xlong,.float,.xfloat
,.word和.string伪指令。
.field伪指令将单个值放入当前字的指定位域。采
用该伪指令可将多个字段或域打包成单个字,直到字
被填满,汇编器不增加SPC。
• 例4-6 该例说明.field伪指令如何将字段打包成字。
假设汇编了下列代码段。
数值 位数
4 000000 6000 .field 3, 3
5 000000 6400 .field 8, 6
6 000000 6440 .field 16, 5
7 000001 0123 .field 01234h,20
000002 4000
8 000003 0000 .field 01234h,32
000004 1234
第4章 汇编语言程序设计
3. 对准段程序计数器SPC的伪指令
对准段程序计数器的伪指令包括:.align伪指令
和.even伪指令。
助记符及语法
说
明
格式
.align [size in 用于将段程序计数器(SPC)对准在
words]
1~128字(必须是2的乘方)的边界。
用于使SPC指到下一个长字的边界
.even
(偶字边界)。相当于 .align 2
第4章 汇编语言程序设计
3. 对准段程序计数器SPC的伪指令
.align伪指令的操作数必须是在20~216之间且等
于2的幂。
例如:操作数为1时,对准SPC到字的边界;
操作数为2时,对准SPC到长字/偶字的边界;
操作数为128时,对准SPC到页面的边界;
没有操作数时,.align伪指令默认为页面边界。
第4章 汇编语言程序设计
【例】 .align伪指令的使用。
源程序:
.field 2,3
.field 11,8
.align 2
.string “Errorcnt”
.align
.byte 4
; 将数值2放入字指定域中
; 打包组成单字——4160h
; 对准长字边界,SPC=02h
; 初始化字符串
; 对准页边界,SPC=80h
; 在当前段中,放入8位数04h
列表文件:
第4章 汇编语言程序设计
0100 0000 0000 0000
1
2
3
4
5
6
000000 4000
000000 4160
(.even)
000002 0045
000003 0072
000004 0072
000005 006f
000006 0072
000007 0063
000008 006e
000009 0074
000080
0004
.field
.field
.align
.string
.align
.byte
2,3
11,8
2
0100 0001 0110 0000
SPC
SPC
SPC
“Errorcnt” SPC
SPC
SPC
SPC
SPC
SPC
SPC
SPC
SPC
SPC
4
000000
000000
000002
000002
000003
000004
000005
000006
000007
000008
000009
000080
000080
4000
4160
0045
0072
0072
006F
0072
0063
006E
0074
004
4. 格式化输出清单文件的伪指令
这类伪指令用于对输出清单文件进行格式化 .
助记符及
说
明
语法格式
.drnolist 用于抑制某些伪指令在清单文件中的出现。
允许.drnolist抑制的伪指令在清单文件中重新
.drlist
出现。
允许按源代码在清单文件中列出条件为假的代
.fclist
码块。汇编器默认状态。 false conditional code block listing
.fcnolist 只列出实际汇编的条件为真的代码块。
调节清单文件输出页面的长度。可
.length page length 针对不同的输出设备灵活调节输出
页面的长度。
.list
允许汇编器将所选择的源语句输出到清单文件。
4. 格式化输出清单文件的伪指令
助记符及语法
续表
说
明
禁止汇编器将所选择的源语句输出到清
.nolist
单文件。
.mlist
允许列出所有的宏扩展和循环块。
.mnolist
禁止列出所有的宏扩展和循环块。
.option
用于控制清单文件的某些功
{B│L│M│R│T│W│X} 能。
{B|L|T|W}limits the listing of .byte,.long,
.string, .word directives to one line.
{R}
resets the B, M, T, and W options.
{M}
turns off macro expansions in listing.
produces a symbol cross-reference
{X}
listing. (You can also obtain a
cross-reference listing by invoking the
assembler with the -x option.)
4. 格式化输出清单文件的伪指令
助记符及语法
格式
.nolist
说
续表
明
禁止汇编器将所选择的源语句输出到清单
文件。
允许列出所有的宏扩展和循环块。
禁止列出所有的宏扩展和循环块。
.mlist
.mnolist
.option
{B│L│M│R│T│W│X} 用于控制清单文件的某些功能。
.page
把新页列在输出清单文件中。
.sslist
允许列出替代符号扩展。
.ssnolist
禁止列出替代符号扩展。
.title“string” 在每页的顶部打印文件标题。
.width page width 调节清单文件页面的宽度。
5. 引用其它文件的伪指令
这类伪指令为引用其它伪指令提供信息。
伪指令及语法
说明
.copy [”]filename[”]
通知汇编器从其它文件中读取源代
码语句,并出现在清单文件中
.def symbol1 [, ... ,
在当前模块中定义的符号,在其它
symboln]
模块中可以使用
.global symbol1 [, ... , 声明符号为全局符号,使其在连接
symboln]
时可被其它模块使用
.include [”]filename[”] 通知汇编器从其它文件中读取源代
码语句,但不出现在清单文件中
.ref symbol1 [, ... ,
在其它模块中定义的符号,在当前
symboln]
模块中可以使用
第4章 汇编语言程序设计
6. 定义宏的伪指令
常用的定义宏的伪指令:
伪指令及语法
.macro
说明
定义宏
.mlib [“]filename[”] 定义宏库
.mexit
相当于一条goto .endm语句。当确
定宏展开将失败时,使用该伪指令
.endm
结束宏代码块
.var
定义一个局部的宏替代符号
第4章 汇编语言程序设计
6. 定义宏的伪指令
如果程序中有一段程序需要执行多次,就可以把
这一段程序定义(宏定义)为一条宏指令,然后在需要
重复执行这段程序的地方调用这条宏指令(宏调用)。
宏的使用需要下列3个步骤:
☆ 宏定义: 在调用宏时,必须首先定义宏;
☆ 宏调用: 在定义宏之后,可在源程序中调用宏;
☆ 宏扩展: 在源程序调用宏指令时,汇编器将对宏
指令进行扩展。
第4章 汇编语言程序设计
1). 宏定义
在调用宏时,必须首先定义宏。有两种方法定义宏:
 可在源文件的开始定义宏,或者在.include或
.copy的文件中定义;
 在宏库中定义。
宏库——是由存档器以存档格式产生的文件集。 宏
库中的每一成员包含一个与成员对应的宏
定义。可通过.mlib指令访问宏库。
第4章 汇编语言程序设计
1). 宏定义
宏定义的格式:
macname .macro [parameter 1][, …, parameter n]
宏程序语句或宏伪指令
[.mexit]
.endm
 macname: 宏程序名称,必须放在源程序标号域。
 .macro: 用来说明该语句为宏定义的第一行伪指令。
 parameters: 任选替代参数,作为宏指令的操作数。
 宏程序语句: 每次宏调用时要执行的指令或汇编命令。
 宏伪指令: 用于控制宏指令展开的命令。
 .mexit: 相当于一条跳到.endm语句。
 .endm: 结束宏定义。
第4章 汇编语言程序设计
1). 宏定义
宏定义的格式:
macname .macro [parameter 1][, …, parameter n]
宏程序语句或宏伪指令
[.mexit]
.endm
如果希望在宏定义中包含有注释,但又不希望这
些注释出现在扩展宏中,可在注释前面加上感叹号
“!”。
如果希望这些注释出现在扩展宏中,需在注释前
面加上符号“*”或“;”。
第4章 汇编语言程序设计
2). 宏调用
在定义宏之后,可在源程序中使用宏名进行宏调用。
宏调用的格式:
[label][:] macname [parameter 1][,…,parameter n]
标号
宏指令名
任选项 位于操作码区
任选的替代参数
数目应与宏指令定义的相等
第4章 汇编语言程序设计
3). 宏扩展
若源程序中调用宏指令,则汇编时就将对宏指
令进行扩展。
扩展时汇编器先将变量传递给宏参数,按宏定
义取代调用宏语句,然后再对源代码进行汇编。
在默认的情况下,扩展宏将出现在清单文件中,
若不需要扩展宏出现在清单文件中,则可通过伪指
令.mnolist来实现。
第4章 汇编语言程序设计
6. 定义宏的伪指令
当汇编器遇到宏定义时,将宏名称放进操作码
表中,并将重新定义前面已经定义过的与之具有相
同名称的宏、库成员、伪指令或指令助记符。
用这种方法可以扩展指令和伪指令的功能以及
加入新的指令。
第4章 汇编语言程序设计
例4-7 宏定义、调用和扩展举例。
1
2
3
4
5
6
7
8
9
10
11
12
* add3
* ADDRP = P1 + P2 + P3
add3 .macro P1, P2, P3, ADDRP;宏定义,宏名称add3
LD
P1, A
;宏程序语句
ADD P2, A
ADD P3, A
STL A, ADDRP
.endm
;宏结束
.global abc, def, ghi, adr
000000 add3 abc, def, ghi, adr;宏调用,替代参数4个
第4章 汇编语言程序设计
;汇编时的宏展开
1
000000 1000! LD
1
000001 0000! ADD
1
000002 0000! ADD
1
000003 8000! STL
abc, A
def, A
ghi, A
A, adr
 其中,3~8行代码定义一个宏add3,它有4个参数:P1,
P2, P3, ADDRP,功能是:ADDRP = P1 + P2 + P3。第
12行代码调用宏add3,它使用了4个参数:abc, def, ghi,
adr。在12行后面的一段代码为宏扩展,是汇编器将宏调
用中提供的变量传递给了宏定义中的参数。
Nesting Level Number
The assembler may precede a line with a number; the number
indicates the nesting level of macro expansions or loop blocks.
第4章 汇编语言程序设计
;汇编时的宏展开
1: LD Smem, dst
1
000000 1000! LD
abc, A
1: ADD Smem, src
1
000001 0000! ADD def, A
1
000002 0000! ADD ghi, A
1
000003 8000! STL
A, adr
! undefined external reference
relocation ’ .text relocatable internal reference
” .data relocatable
type
+ .sect relocatable
- .bss, .usect relocatable
% complex relocation expression
1: STL src, Smem
7. 条件汇编伪指令
 用来通知汇编器按照表达式计算出的结果的真假
,决定是否对某段代码进行汇编。
有两组伪指令用于条件代码块的汇编:
(1) .if/.elseif/.else/.endif伪指令
用于通知汇编器按照表达式的计算结果,对某段代码
块进行条件汇编。要求表达式和伪指令必须完全在同
一行指定。
(2) .loop/.break/.endloop伪指令
用于通知汇编器按照表达式的计算结果重复汇编一个
代码块。
7. 条件汇编伪指令
助记符及语法格式
.if well-defined
expression
.elseif well-defined
expression
.else well-defined
expression
说
明
标记条件块的开始。仅当.if条件为真时,
对紧接着的代码块进行汇编。
若.if条件为假,而.elseif条件为真时,
对紧接着的代码块进行汇编。
若.if条件为假,对紧接着的代码块进行汇
编。
标记条件代码块的结束,并终止该条件
.endif
代码块。
.loop [well-defined 按照表达式确定的次数进行重复汇编的
expression]
代码块的开始。表达式是循环的次数。
若.break表达式为假,通知汇编器继续
.break [well-defined
重复汇编;而当表达式为真时,跳到紧
expression]
接着 .endloop后面的代码。
.endloop
标记代码块的结束。
8. 汇编时间符号伪指令
汇编时间符号伪指令将符号与常数值或字符串进行等价。
伪指令及语法
说明
.asg [“]character string 将一个字符串赋给替代符号,
[”], substitution symbol 并存在替代表中,替代符号
可以重新定义
.eval well-defined
计算一个表达式,将其结果
expression, substitution 转换成字符,并将字符串赋
symbol
给替代符号
.equ
给符号赋值,符号存在符号
例如:INDEX .equ 100
表中,不能被重新定义
.set
将值赋给符号,符号被存在
例如:INDEX .set 100
符号表中,不能被重新定义
8. 汇编时间符号伪指令
伪指令及语法
.label symbol
说明
定义一个特殊的符号,用来指出在
当前段内的装入时间地址
.struct
设置类似C的结构定义
.endstruct
结束结构体
.union
建立类似C的union(联合)定义
.endunion
结束union(联合)
.tag
给类似C的结构表赋上一个符号
.struct和.endstruct用来设置类似C的结构定义,只是产生一
个可重复使用的符号模板,而不分配存储器。
.tag将结构体与一个标号联系起来,.tag伪指令不分配存储
器,且结构体的标记符必须在使用之前先定义好。
第4章 汇编语言程序设计
汇编时间符号伪指令举例
例4-8 伪指令.struct和.endstruct的使用。
type
X
Y
T_LEN
COORD
.struct ; 结构标记符定义
.int
.int
.endstruct
.tag
type ;声明COORD
ADD COORD.Y, A
.bss COORD, T_LEN;实际的存储器配置
8. 汇编时间符号伪指令
 .union/.endunion伪指令通过创建符号模板,提供
在相同的存储区域内管理多种不同的数据类型的
方法。
 .union不分配任何存储器,它允许类型和大小不同
的定义临时地存储在相同存储器空间。
 .tag伪指令将union属性与一个标号联系起来,可
以定义一个union并给定一个标记符,以后可用
.tag伪指令将它声明为结构体的一个成员。
例4-9 .union/.endunion伪指令举例。
.data
s2_tag .struct ;结构标记符定义
.union ;union是第一个结构成员
.struct ;结构是union成员
h1
.half
;h1, h2和w1存在于相同的存储器中
h2
.uhalf
.endstruct
w1
.word ;字是另一个union成员
.endunion
w2
.word ;第二个结构成员
s2_len .endstruct
XYZ
.tag s2_tag
.bss
XYZ, s2_len ;声明结构的实例
ADD XYZ.h2, A
.text
ADD @(XYZ.h2),A
9.混合伪指令
常用的混合伪指令:
助记符及语法
说
明
格式
.end
终止汇编,位于程序源程序的最后一行。
.far_mode
通知汇编器调用为远调用。
为存储器映像寄存器定义符号名。使
.mmregs
用.mmregs的功能和对所有的存储器映像
寄存器执行.set伪指令相同。
.newblock
用于复位局部标号。
确定运行指令的处理器,每个’C54x器
.version [value]
件都有一个与之对应的值。
.emsg string 把错误消息送到标准的输出设备。
.mmsg string 把汇编时间消息送到标准的输出设备。
.wmsg string 把警告消息送到标准的输出设备。
第4章 汇编语言程序设计
9.混合伪指令
.newblock伪指令用于复位局部标号。
局部标号是形式为$n或name?的符号。当它们出
现在标号域时被定义。局部标号可用作跳转指令的
操作数的临时标号。
.newblock伪指令通过在它们被使用后将它们复
位的方式来限制局部标号的使用范围。
第4章 汇编语言程序设计
9.混合伪指令
 有3个伪指令可以允许用户定义自己的错误和警告
消息:
 .emsg伪指令以和汇编器同样的方式产生错误,增
加错误的计数并防止汇编器产生目标文件。
 .wmsg伪指令的功能与.emsg伪指令相似,但它增
加警告计数,而不增加错误计数。它也不影响目
标文件的产生。
 .mmsg伪指令的功能与.emsg和.wmsg伪指令相似,
但它不增加错误计数或警告计数。也不影响目标
文件的产生。
第4章 汇编语言程序设计
4.4 C54x汇编语言的有关知识
 汇编语言是一种面向CPU指令系统的低级语言。汇
编语言源程序中包含汇编语言指令Assembly
Language Instructions 、汇编伪指令Assembler
Directives、宏伪指令Macro Directives和一些规
定的数字、字符、符号地址及表达式等。
 下面讨论C54x汇编语言源程序的有关知识,包括汇
编语言源程序的格式,各种数字、符号和表达式的
规定;汇编伪指令的使用;汇编器、连接器的调用
方法和选项等。
第4章 汇编语言程序设计
4.4.1 汇编语言源程序的格式
用C54x汇编语言编写的源程序行通常包含4个部
分:标号区、助记符区、操作数区和注释区。
助记符指令语法格式:
[标号][:]
助记符
[操作数]
例4-10】 指令格式举例。
x
.set
200H
Begin: STM #x,AR1
STL
A, *AR1
标
号
助记符
操作数
[; 注释]
; 符号x=200H
; 将200H加载到AR1
;(A)→(AR1)
注
释
第4章 汇编语言程序设计
语句的书写规则:
① 所有语句必须以标号、空格、星号或分号
(*或;)开始;
② 标号是可选项,若使用标号,则标号必须
从第一列开始;
③ 所有包含有汇编伪指令的语句必须在一行
完成指定;
④ 各部分之间必须用空格分开,Tab字符与空
格等效;
第4章 汇编语言程序设计
语句的书写规则:
⑤ 程序中注释是可选项。如果注释在第一列开
始时,前面必须标上星号或分号,在其他列
开始的注释前面必须以分号开头;
⑥ 如果源程序很长,需要书写若干行,可以在
前一行用反斜杠字符(\)结束,余下部分接
着在下一行继续书写。
第4章 汇编语言程序设计
1. 标号字段(Label Field)
所有汇编指令和大多数汇编伪指令都可以选用标号,
供本程序或其它程序调用。
☆ 标号必须从第一列开始。
☆ 标号最长32个字符,由英文字母、数字、下划
线和美圆符号(A~Z,a~z,0~9,_和$)等组成,但
第一个字符不能是数字。
☆ 标号分大小写。
☆ 标号后面可以带冒号,但冒号并不处理为标号名
的一部分。
☆ 若不使用标号,则语句的第一列必须是空格、星
号或分号。
第4章 汇编语言程序设计
1. 标号字段(Label Field)
 (1)当使用标号时,标号的值是SPC的当前值。
例4-11 使用.word伪指令初始化几个字,其标号
Start将指向第一个字。
该例中标号Start的值为000040H。
…
9 000000
10 000040
000041
000042
…
;假设汇编了某个其他代码
000A
0003
0007
Start: .word 0Ah,3,7
标号,值为40h
第4章 汇编语言程序设计
1. 标号字段(Label Field)
 (2) 在一行指令中,标号本身是一个有效的语句。标号
将SPC的当前值赋给标号,等效于下列伪指令句:
label .set $
;$提供SPC的当前值
 (3) 当标号独自占一行时,标号指向下一行指令,
而SPC的值不增加。
例如,下列标号Here的值为000043H。
000043
Here:
000043
0003
. word 3
2. 助记符字段Mnemonic Fields
• 助记符规定了指令所实现的操作功能。它们不能从
第一列开始,若从第一列开始,则被认为是标号。
助记符部分可包含下列操作码之一:
 ① 机器―指令助记符,例如:ADD,MAC,STH,
大小写均可;
 ② 汇编伪指令,例如:.data,.list,.set,以“.”
作为前缀,必须小写;
 ③ 宏伪指令,例如:.macro,.var,.mexit,以
“.”作为前缀,必须小写;
 ④ 宏调用。
3. 操作数字段Operand Field
操作数字段给出参与操作的数据来源及存放结果的
目标单元。该部分是一个操作数列表,可以是常数、
符号或表达式。 STM #x, AR1
.bss X, 1
☆一般位于最左边的是源操作数,中间者(可有可
无)是移位的位数,最右边的是目标操作数。
☆ 汇编器指定常数、符号或表达式用来作为地址
、立即数或间接地址。
☆ 指令操作数可使用前缀# 、*和@,汇编器将带
前缀#的操作数处理为立即数,将带前缀*的操作数
处理为间接地址,[email protected]
址时的地址偏移量。
第4章 汇编语言程序设计
4. 注释字段Comment Field
• 注释可以增强程序的可读性,便于阅读、修改和
调试程序。注释中可包含ASCII字符和空格,可
使用英文或中文书写。
注意:若注释从第一列开始,则须以分号或星号开
头;若注释从其他任何列开始,则必须用分号而
不能使用星号。
4.4.2 汇编语言中的常数及字符串
汇编器可支持以下几种类型的常数:
数据类型
二进制
八进制
十进制
十六进制
字符常数
字符串
浮点常数
举
例
说 明
1100001b或1100001B
216q或532Q或0216(零开头)
1234或+1234或-1234
缺省型
0B40h或0B40H或0xB40
‘D’
“it is a string”
1.523e-23
仅用于C语言
汇编-时间
X
常数
.set
50
使用.set伪指
令
第4章 汇编语言程序设计
4.4.3 汇编源程序中的符号(Symbols)
汇编源程序中符号可用来作标号Labels、常数constants
和替代字符substitution symbols。
☆ 由字母、数字以及下划线和美元符号(A~Z,
a~z,0~9,_和$)等组成;
☆ 符号名最多可长达200个字符;
☆ 在符号中,第1位不能是数字,并且符号中不
能含空格。
第4章 汇编语言程序设计
4.4.3 汇编源程序中的符号(Symbols)
1. 标号Labels:用作标号的符号和程序的位置有关,
在程序中作为符号地址。
2. 符号常数:通过下列两种方法可将常数值赋给符号
☆ 通过伪指令.set、.equ和.struct/.tag/.endstruct
将常数值赋给符号名。
☆ 使用汇编器的-d选项使常数值与符号相等。
asm500 -d name=[value]
第4章 汇编语言程序设计
4.4.3 汇编源程序中的符号Symbols
3. 替代符号Substitution Symbols:
将代表一个变量的字符串值赋给符号,这时符
号名与该变量等效,成为字符串的别名。
.asg “*+”, INC ; indirect auto-increment
4. 局部标号Local Labels:
它是一种特殊标号,它的使用范围和影响是临时
性的。
局部标号可用2种方法定义:
☆ $n,n=0~9。
☆ name?,这里name是合法符号名。
第4章 汇编语言程序设计
4.4.3 汇编源程序中的符号
4. 局部标号:
局部标号可用下述4种方法之一来取消定义或复位:
☆
使用.newblock伪指令;
☆
改变段(利用伪指令.sect,.text或.data);
☆
通过进入一个include文件(指定.include或
.copy伪指令);
☆
通过离开一个include文件(达到included文件的
结尾)。
例4-12:局部标号$n的应用举例。
假设符号ADDRA,ADDRB,ADDRC已经在前面作了定义。
Label1: LD
ADDRA,A
SUB ADDRB,A
BC
$1,ALT
LD
ADDRB,A
B
$2
$1
LD
ADDRA,A
$2
ADD ADDRC,A
.newblock
BC
$1,ALT
BC
STL $1,ALT
A,ADDRC
STL
$1
NOP A,ADDRC
$1
NOP
;将ADDRA装入累加器A
;减去地址B
;如果小于0,分支转移到$1
;否则将ADDRB装入累加器A
;分支转移到$2
;$1:将ADDRA装入累加器A
;$2:加上ADDRC
;;若小于0,分支转移到$1
取消$1的定义,使它可被再次使用
.newblock
;若小于0,分支转移到$1
;存ACC的低16位到ADDRC
;存ACC的低16位到ADDRC
;错误:$1被多次定义
第4章 汇编语言程序设计
4.4.4 汇编源程序中的表达式Expressions
允许将表达式作为操作数使用。汇编时先计算出
表达式的值,然后将该值填入目标代码中。
1. 运算符Operators (下页表4.10)
’C54x汇编器使用与C语言相似的优先级。
相同优先级的运算按从左到右的顺序
2. 条件表达式Conditional Expressions
汇编器支持关系操作,可以用于任何表达式。
= 等于
> = 大于或等于
> 大于
= = 等于
< = 小于或等于
< 小于
!= 不等于
表4.10 指令系统中的运算符及优先级
符号
+ - ~ !
操作
取正、取负、按位求补、逻辑负
* / %
+ -
^
« »
< <=
> >=
!=
=(=)
&
∧
|
乘法、除法,求模
加法,减法
指数
左移,右移
小于,小于或等于
大于,大于或等于
不等于
等于
按位与运算(AND)
按位异或运算(exclusive OR)
按位或运算(OR)
运算的优先级
从右到左
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
从左到右
第4章 汇编语言程序设计
3.关于表达式的合法性(Well-Defined Expressions)
某些汇编器要求有效定义的表达式作为操作数。操
作数可以是汇编时间常数或链接时可重定位的符号。
所谓合格的表达式是指表达式中的符号或汇编时
间常数在被使用之前都已被定义过。
合格表达式的计算必须是绝对的(absolute)。
3.关于表达式的合法性
例4-14 合格的表达式举例。
label1
label2
X
goodsym1
goodsym2
goodsym3
goodsym4
.data
.word
.word
.word
.word
.set
.set
.set
.set
.set
0
; 将16位值0,1,2放入标号为
label1的当前段连续字中
1
2
3
; 将3放入标号为label2的字中
; 定义X的值
50h
l00h + X ; 有效定义的表达式
$
; $提供SPC的当前值
label1 ; 引用已定义的局部标号
label2-label1 ; 有效定义的表达式
第4章 汇编语言程序设计
3.关于表达式的合法性
所有合法表达式可化简为以下2种形式之一:
 绝对符号。绝对符号是指其值不能改变的符号。
 可重新定位符号±绝对符号。表达式若不能简化
为仅含一个可重新定位符号是非法的,因为这种符
号不能被分辨。表达式也不能包含可重新定位符号
和外部符号的乘或除。
Expressions that cannot be reduced to contain only
one relocatable symbol are illegal.
表4.11 带有绝对符号和可重新定位符号的表达式的合法性
若A为
绝对
绝对
绝对
可重新定位
可重新定位
可重新定位
外部
外部
外部
并且若B为
绝对
外部
可重新定位
绝对
可重新定位
外部
绝对
可重新定位
外部
A+B为
绝对
外部
可重新定位
可重新定位
非法
非法
外部
非法
非法
A-B为
绝对
非法
非法
可重新定位
绝对*
非法
外部
非法
非法
* A和B必须在相同的段,否则为非法。
Symbols or registers that have been defined as global
with the .global directive are referred to as external.
例4-15 说明在表达式中绝对符号和可重新定位符号
的使用。
下面的程序中,使用了4个定义在相同段的符号。
.global extern_1 ; 定义在外部的全局符号
intern_1:.word ‘D’ ; 定义在现行模块中,可重新定位
LAB1:
.set
2
intern_2:.word
LD
LD
; LAB1=2,绝对符号
3
; 定义在现行模块中,可重新定位
#LAB1+((5+4)*3),A ; LAB1为绝对符号,A=29
#LAB1+3+(4*7),A ; LAB1为绝对符号,
A=33
第4章 汇编语言程序设计
例4-16 表达式的合法性分析
判断下列指令中表达式的合法性。
外部
合法
LD
extern_1-10,B
LD
10-extern_1,B 不可将重新定位符号变负 非法
LD
-(intern_1),B
非法
可重新定位符号不可变负
LD
extern_1/10,B
LD
intern_1 + extern_1,B
可重新定位符号不可乘除
非法
非法
可重新定位+可重新定位=非法
第4章 汇编语言程序设计
例4-17 表达式的合法性分析
判断下列指令中表达式的合法性。
LD intern_1 - intern_2 + extern_1,B
合法
绝对符号+可重新定位
可重新定位
可重新定义-可重新定义=绝对符号
绝对符号
可重新定位
可重新定位
LD intern_1 + intern_2 + extern_1,B
非法
可重新定义+可重新定义=非法
LD intern_1 + extern_1 - intern_2,B
可重新定义+可重新定义=非法
非法
第4章 汇编语言程序设计
4.5 汇编语言程序设计
• 4.5.1 DSP基本汇编程序的设计
汇编语言程序具有3种结构形式:
☆顺序结构——指令按顺序被逐条执行,在程序
中没有分支和循环,也不调用子程序 。
☆分支结构——是根据条件是否满足决定程序走
向的一种结构 。
☆循环结构——如果有一段程序需要多次重复执
行时,就可以使用循环结构。
第4章 汇编语言程序设计
1.顺序结构
初始化程序、算术运算程序、查表程序等就采
用这种结构。
例4-19 用立即寻址方式设置初值。
STM
#00a8H, PMST
STM
#0000H, SWWSR
STM
#Data_0, AR2
STM
#Data_1, AR3
第4章 汇编语言程序设计
2.分支程序
 分支结构又分为单分支和多分支结构。
 汇编语言中程序的分支是由条件转移指令实现的。
 C54x CPU以累加器A、B及标志位C、TC、OVA、OVB
等的状态作为条件,判断程序是否转移。
第4章 汇编语言程序设计
2.分支程序
例4-21
编写程序,比较两数data0和data1的大小。若两者相等,
则将其值存入data2单元。否则将大者存入data2单元。
方法1: 使用CMPS 指令(顺序结构)
data0 .set 200
data1 .set 100
.bss data2, 1
.text
LD #data0, 16, a ;将data0送入A(31~16)
Add #data1, A;
将data0送入A(15~10)
CMPS A, data2 ;
比较、选择和存储大者
.end
方法2:使用CMPR 指令
data0 .set 200
data1 .set 100
.bss data2, 1
.text
STM #data0, AR0;
STM #data1, AR3
CMPR 0, AR3
BC d1, NTC
BD d2
NOP
NOP
d1 : CMPR 1, AR3
BC d2, TC
MVMD AR3, data2
BD loop
NOP
NOP
d2:
MVMD AR0, data2
loop: NOP
.end
CMPR CC, ARx
If (cond), Then 1→TC
Else 0→TC
第4章 汇编语言程序设计
3.循环程序
循环程序通常由下列4部分组成:
 置循环初值
 循环体(循环处理部分)
 循环控制部分
 修改控制变量
STM
#99,AR1;
Loop: RPT
#999 ;
NOP ;
BANZ loop, *AR1- ;
3.循环程序
例4-23 写出计算 y 
解:
6

a i x i的主要汇编程序。
i 1
.bss a, 6
.bss x, 6
.bss y, 1
Table: .word 1,2 ,3,4,5, 6
.text
(Xmem)×(Ymem)+(src)→dst
STM #a,AR1
(Xmem) → T
RPT
#5
MVPD Table, *AR1+
STM
#a,AR3
STM
#x,AR4
STM
#y,AR7
RPTZ A, #5 ;累加器清0,下条指令重复执行6次
MAC *AR3+,*AR4+,A ;
STL
A,*AR7
3.循环程序
例4-24 采用多重循环的延时程序。 设机器周期为20ns,
则下列程序的延时时间为:
20ns×[2+(1+1000+4)×100 ]=2010400ns≈2ms
STM #99,AR1;2个机器周期
Loop: RPT
#999 ;1个机器周期
NOP ;1个机器周期,内循环1000次
BANZ loop, *AR1- ;4个机器周期(条件真)
;2个机器周期(条件假)
NOP
NOP
NOP
NOP
第4章 汇编语言程序设计
4.5.2 DSP的模块化程序设计及汇编连接过程
 在编写C54x汇编程序时,可将程序分为多个模
块(或文件),每一程序模块都有明确的任务和功
能。
 根据每个模块的不同功能,选择结构、伪指令
和指令进行编程,然后将多个文件组合在CCS环境
的同一工程(project)中,通过汇编连接,最终形成
一个可执行文件。
1.编写中断处理程序
例4-25: 有定时硬件中断时,为防中断跑飞:
通过中断处理程序开辟出中断矢量表的存储空间,
NMI: RETE ;外部中断1,开中断返回
进行中断入口地址的跳转处理。
NOP ;
NOP ;
例4-26 如果只进行软件仿真调试,而没有硬件中断产
NOP ;
生,则可以采用下列简单的复位中断处理程序。
sint17 .space 4*16 ; 保留空间
.ref
_c_int00
.....
.sectTINT0:
"vectors"
BD _timer_isr;转定时中断服务程序
PSHM ST0;
int_RESET:
PSHM ST1;
BD _c_int00;复位时跳入主程序的
_c_int00
.....
NOP
DMAC5: RETE;DMA通道5中断,开中断返回
NOP
NOP ;
.space 124*16
;没有使用其它中断,
保留空间
NOP
;
NOP ;
.end
第4章 汇编语言程序设计
2.编写主程序和头文件
 应尽量使主程序结构简洁,以函数调用为主,突
出主程序的主体轮廓。
 对重复出现的算法或较复杂的程序部分,可将其
编写成子程序或宏。
 可将一些全局标号、常量、变量、寄存器名、位
名等存放在一个或几个头文件中,做为共享文件来
使用。
3.编写命令文件
参考4.2.3节。
命令文件负责为连接器提供段定位信息。
例4-28
命令文件test.cmd
vectors.obj
SECTIONS
test.obj
{ .text:>
EPROM
-o test.out
.data:>
EPROM
-m test.map
.bss:>
SPRAM
.STACK:> DARAM
MEMORY
.vectors:> VECS
{
}
PAGE 0:
EPROM: org=0xE000, len=0x100
VECS:
org=0xFF80, len=0x80
PAGE 1:
DARAM: org=0x0080, len=0x20
SPRAM: org=0x0100, len=0x0020
}
PAGE 0
PAGE 0
PAGE 1
PAGE 1
PAGE 0
第4章 汇编语言程序设计
4.编辑、编译、汇编和连接生成各种文件
1)编辑:用户可在任何文本编辑环境下编写C源文
件.c或汇编源文件.asm。
2)编译:若采用C语言,则需要调用C编译器将.c
文件编译成汇编语言文件.asm。
3)汇编:用汇编语言编写的源程序或者来自C编译
器编译的汇编源程序被送入汇编器进行汇编。
参考:TMS320C54x Code Composer Studio
Tutorial.pdf,spru327c,2000,TI官网
第4章 汇编语言程序设计
3)汇编
2
**********************************
汇编器主要完成下列工作:
3
** 汇编一个初始化表到.data段 **
4 将汇编语言源文件汇编产生一个可重新定位的目
**********************************

5
0000
.data
标文件(后缀.obj)。
6
0000 0011 coeff
.word 011h,022h,033h
0001 0022
 根据需要,产生源程序列表文件(后缀.lst),并对
0002 0033
源程序列表文件进行控制。
7
**********************************
8 将代码分为若干段,为每个目标代码段都设置一
** 在.bss段中为变量保留空间 **

9
**********************************
个段程序计数器SPC。
10 0000
.bss
buffer,10
11 定义和引用全局符号。
**********************************

12
** .bss结束后仍然在.data 段中
**

13 汇编条件块。**********************************
14 支持宏定义和宏调用。
0003 0123 prt
.word
0123h

第4章 汇编语言程序设计
ASM500命令格式如下:
asm500 [input file [object file [listing file]]] [-options]
 input file: 汇编源文件名,缺省后缀为.asm
 object file: 编译输出的OBJ文件名,缺省后缀为.obj
 listing file: 产生的列表文件名,缺省后缀为.lst
 options: 编译器使用的各种选择。选项举例:
 -c:若使用该选项,编译器忽略字母的大小写。例
如abc与ABC是一样的。系统缺省为区分大小写。
3)汇编
表4.12
C54x汇编器的选项及功能
功 能
[email protected](文件名)可以将文件名的内容附加到命令行
上, 避开命令行长度的限制。在一个命令文件中,文件
-@
名或选项参数中包含了嵌入的空格或连字号,则必须使
用引号括起来,例如:“this-file.asm”
-a
建立绝对列表文件。选用-a时,汇编器不产生目标文件
-c
使汇编语言文件中大小写没有区别
为名字符号设置初值。格式为-d name[=value]时,与汇
-d
编文件被插入 name.set[=value]是等效的。
抑制汇编器给没有.asm扩展名的文件添加扩展名的默认
-f
行为
允许汇编器在源代码中进行代码调试。汇编语言源文件
-g
中每行的信息输出到COFF文件中。
-h, -help, -? 这些选项任一个将显示可供使用的汇编器选项的清单
-hc
将选定的文件复制到汇编模块。
-hi
将选定的文件包含到汇编模块。
选项
3)汇编
选项
-i
-l
-mf
-mg
-q
-r, -r[num]
-pw
-u
-v
-s
-x
续表4.12
功 能
规定一个目录,汇编器可以在这个目录下找
到.copy、.include或.mlib命令所命名的文件 。
(英文小写l)生成一个列表文件
指定汇编调用扩展寻址方式
源文件是代数式指令
抑制汇编的标题以及所有的进展信息
压缩汇编器由num标识的标志。
对某些汇编代码的流水线冲突发出警告
-u name取消预先定义的常数名,不考虑-d选项所指
定的常数
-v value确定使用的处理器,可用
541,542,543,545,5451p,5461p,548,549值中的一个
把所有定义的符号放进目标文件的符号表中。
产生一个交叉引用表。
第4章 汇编语言程序设计
4)连接
连接器将目标文件合成为可执行的.out文件。
它主要完成下列任务:
 按照目标系统的实际硬件将段配置到存储器空间;
 对符号和段进行重新定位,并确定最后的地址;
 确定输入文件之间未定义的外部引用。
连接器的命令行格式如下:
lnk500 [-options] filename1 … filenamen
扩展名.obj文件
4)连接
表 4-13 C54x连接器的常用选项及功能
功能
生成一个绝对地址的、可执行的输出模块。
-a
生成一个可重新定位、可执行的目标模块。
-ar0
定义一个全局符号,所对应的程序存储器地址,
-e
global_symbol 称为入口地址。
对输出模块各段之间的空单元设置一个16位数值
-f fill_value
(fill_value)。
选项
-i dir
-l filename
-m filename
更改搜索文档库算法,先到dir(目录)中搜索。
命名一个文档库文件作为链接器的输入文件 。
生成一个.map映像文件,filename是其文件名。
-o filename
对可执行输出模块命名。如果默认,则此文件名
为a.out
-r
生成一个可重新定位的输出模块。
第4章 汇编语言程序设计
5)调试
.out文件提供的指令代码可送入CCS调试环境
进行调试,以验证程序的正确性。
编程者还可通过选项获得下列的两个文件,它们
在调试的过程中会对编程者有所帮助 :
 通过汇编器的选项-l产生一个后缀为.lst的列表
文件。(如例4-29 或见例4-2 )
 通过连接器的选项-m产生一个后缀为.map的映射
文件。(如例4-30)
第4章 汇编语言程序设计
5)调试
.out文件提供的指令代码可送入CCS调试环境
进行调试,以验证程序的正确性。
编程者还可通过选项获得下列的两个文件,它们
在调试的过程中会对编程者有所帮助 :
 通过汇编器的选项-l产生一个后缀为.lst的列表
文件。(如例4-29)
 通过连接器的选项-m产生一个后缀为.map的映射
文件。(如例4-30)
第4章 汇编语言程序设计
5)调试
.out文件提供的指令代码可送入CCS调试环境
进行调试,以验证程序的正确性。
编程者还可通过选项获得下列的两个文件,它们
在调试的过程中会对编程者有所帮助 :
 通过汇编器的选项-l产生一个后缀为.lst的列表
文件。(如例4-29)
 通过连接器的选项-m产生一个后缀为.map的映射
文件。(如例4-30)
第4章 汇编语言程序设计
4.5.3 DSP定点算法设计
1. 定点数的定标
计算机有两种数据表示方法:

定点数表示法

浮点数表示法
定点数就是小数点位置固定的数。数据的表示形
式是:
符号位 整数部分.小数部分
C54x是定点芯片,采用补码形式来表示无符号数
和有符号数。
第4章 汇编语言程序设计
4.5.3 DSP定点算法设计
2. Q表示法
CPU在执行指令时,并不知道处理的数据是
整数还是小数,也不能指出小数点的位置。在
编程时必须由程序员指出一个数的小数点处于
哪一位,这就是定标的概念。
常用的定标方法是Q表示法,Q表示法用Q0、
Q1、…Qi、…、Q15分别表示小数点在D0位之后、
D1位之后、…Di位之后、…D15位之后。
表4.14
Q表示
Q15
Q14
Q13
Q12
Q11
Q10
Q9
Q8
Q7
Q6
Q5
Q4
Q3
Q2
Q1
Q0
Q表示法
小数点位置 整数位 小数位
0
15
在D15之后
1
14
在D14之后
2
13
在D13之后
3
12
在D12之后
4
11
在D11之后
5
10
在D10之后
6
9
在D9之后
7
8
在D8之后
8
7
在D7之后
9
6
在D6之后
10
5
在D5之后
11
4
在D4之后
12
3
在D3之后
13
2
在D2之后
14
1
在D1之后
15
0
在D0之后
十进制表示范围
-1~0.9999695
-2~1.9999390
-4~3.9998779
-8~7.9997559
-16~15.9995117
-32~31.9990234
-64~63.99804375
-128~127.9960938
-256~255.9921875
-512~511.9804375
-1024~1023.96875
-2048~2047.9375
-4096~4095.875
-8192~8191.75
-16384~16383.5
-32768~36767
精度--幂
2 -15
2 -14
2 -13
2 -12
2 -11
2 -10
2 -9
2 -8
2 -7
2 -6
2 -5
2 -4
2 -3
2 -2
2 -1
20
第4章 汇编语言程序设计
4.5.3
DSP定点算法设计
2. Q表示法
4.5.3
DSP定点算法设计
3. Q值的确定
在使用定点定标时,如何选择合适的Q值是一个
关键性问题。在实际的DSP工程环境中,参与运算
的变量都有一定的动态范围,只要这个动态范围确
定了,Q值也就确定了。
为了防止异常或溢出,应该将Q值取低,即将
数据格式放大。
4.5.3
DSP定点算法设计
4.定点算术运算
在数字信号处理算法中,大量运算是乘法和累加。
一般情况下,应尽量采用纯整数运算或纯小数运算,
即全部数据用Q0格式表示,或用Q15格式表示。
以下主要介绍:
 定点加法运算
 定点乘法运算
1)定点加法运算
两定点数相加注意下列两点:
 被加数和加数必须有相同的Q值;
 结果是否会溢出。
1)定点加法运算
例4-35 计算0.5+0.89=1.39。被加数和加数采用Q15就
可满足,但其和却超出了Q15的表示范围,即产生了溢
出。解决的方法是将数据进行Q14定标。程序段如下:
.bss x,2
.bss sum,1
table: .word 5*16384/10 ; 0.5的Q14定标
.word 89*16384/100 ; 0.89的Q14定标
.text
STM #x,AR2
RPT #1
MVPD table,*AR2+
LD x,A
ADD x+1,A
STL A,*AR2
2)定点乘法运算
因为16位×16位=32位,所以乘法不会产生溢出。
两定点数相乘通常有下列三种情况:
 整数×整数:Q0×Q0=Q0,结果仍为纯整数,
小数点在结果的D0位后面。
 小数×小数:Q15×Q15=Q30,结果仍为纯小
数,小数点在乘积的D30位后面,也就是说,D31
和D30位都是符号位,且其值相同。
 混合小数乘法:Qi×Qj = Qi+j
2)定点乘法运算
例4-37 混合小数乘法:计算7.62×1.84 = 14.0208。
程序段如下:
.bss
x,2
.bss
prod,2
table: .word 762*4096/100; 7.62的Q12定标
.word 184*16384/100;1.84的Q14定标
.text
STM
#x,AR2
RPT
#1
MVPD table,*AR2+
STM
#x,AR4
STM
#x+1,AR5
MPY
*AR4,*AR5,A
DST A,prod;乘积为Q26定标,32位,没有进行
移位和只保留高16位的处理。
第4章 汇编语言程序设计
4.5.4 流水线冲突及其解决的方法
 采用C/C++语言编程,经过C编译器产生的代
码避免了资源争用和时序上的错误,不会产生流
水线冲突。
 采用汇编语言编程,在下列情况下可能会产
生流水线冲突:
1.对MMR进行写操作所引发的流水线冲突
2.条件执行指令有可能发生的流水线冲突
3.改变PMST可能引起的流水线冲突
1.对MMR进行写操作所引发的流水线冲突
对下列硬件资源进行写访问时有可能产生未保护
性的流水线冲突(IMR,IFR,TRN,REA,RSA,XPC除外):
 累加器AG、AH、AL、BG、BH、BL
 状态寄存器ST0、ST1
 处理器工作方式状态寄存器PMST
 辅助寄存器AR0~AR7
 堆栈指针SP
 暂存器T
 块重复计数器BRC
 重复块长度寄存器BK
1.对MMR进行写操作所引发的流水线冲突
例4-38 分析下列指令的流水线冲突及解决方法。
STLM
A,AR1;(A)→AR1
STM
#8,AR2;8→AR2
它们的流水线操作如下图所示。两条指令在写MMR
时产生了资源争用,也就产生了流水线冲突。
时序性流水线冲突
1.对MMR进行写操作所引发的流水线冲突
解决方法是:在两条指令之间插入1个空操作NOP,
则流水线变为下图所示。写AR2的时间延时了一个周期,
避开了写操作的资源争用,解决了流水线的冲突。
第4章 汇编语言程序设计
2.条件执行指令有可能发生的流水线冲突
例4-40 分析下列程序的流水线操作情况,其流水线
如下图所示。
LD
*AR2,B
XC
2,BEQ ;若(B)=0,则执行后面的2条指令
……
逻辑性流水线冲突
第4章 汇编语言程序设计
2.条件执行指令有可能发生的流水线冲突
解决的方法是:在两条指令中插入2个NOP,
使得条件稳定后再去进行条件检测。
3.改变PMST可能引起的流水线冲突
在处理器工作方式状态寄存器(PMST)中有一些非
常重要的位,在修改PMST的这些位时,如果紧跟其
后的指令立即使用新的地址空间去进行访问,就有
可能产生错误。
例4-41 在修改DROM位之后,插入3个NOP,才能去访
问它所影响的存储空间。
ORM #8h, PMST;令DROM = 1,本例设DP=0
NOP
NOP
NOP
LD
*AR3, A ;从片内ROM读数据
第4章 汇编语言程序设计
3.改变PMST可能引起的流水线冲突
例4-42 在修改MP/MC位之后,插入2个NOP,才能对它
所配置的存储空间进行操作。
STLM
A, PMST
;该指令使MP/MC=1
NOP
NOP
CALLD
offchip ;调用片外程存子程序offchip
STM
#k, AR1
解决流水线冲突方法(表4-15访问MMR的建议)
通过前面分析看出,解决流水线冲突的方法主要是:
1)插入NOP指令,延长流水线的执行时间。
2)选用合适的指令,避免产生逻辑性错误。
例4-43 分析程序段的流水线操作。
RSBX SXM
;SXM清零
ADD *AR1(10h),A ;((AR1+10h))+(A)→A,双字双
书中指令ADD *AR1,A前应插入NOP指令 周期指令
在RSBX SXM指令的后面本应该插入一个NOP,但由
于ADD *AR1(10h),A 指令为双字指令,隐含了一个保
护周期,因此,两条指令之间不需要再插入NOP。
作业
习题4.2,4.4, 4.5,4.8, 4.11,
4.18,4.19

similar documents