Download presentation
Presentation is loading. Please wait.
1
第4章 汇编语言程序设计 本章结合C54x的软件开发过程,介绍DSP所采用的COFF目标文件格式、结构和规范。
介绍汇编语言重要组成:伪指令Assembler directives和宏指令Macro directives。 讨论建立汇编语言程序并产生可执行文件的设计要求。指出汇编程序设计中的一些关键问题,并通过实例介绍设计的方法和技巧。 参考: TMS320C54x Assembly Language Tools User’s Guide .pdf, SPRU102F,2002年 TMS320C54x Code Composer Studio Tutorial. pdf spru327c,2000,TI官网
2
第4章 汇编语言程序设计 目录: 4.1 C54x的软件开发过程 4.2 公共目标文件格式COFF 4.3 汇编器的伪指令
4.5 汇编语言程序设计
3
4.1 C54x的软件开发过程 提供2种编程语言:汇编语言 C/C++语言
第4章 汇编语言程序设计 4.1 C54x的软件开发过程 提供2种编程语言:汇编语言 C/C++语言 对于完成一般功能的代码,这两种语言都可使用,但对于一些运算量很大的关键代码,最好采用汇编语言来完成,以提高程序的运算效率。 C54x的软件开发过程可以分为文本编辑、编译、汇编和连接这样四个基本步骤,如图4-1所示。
4
第4章 汇编语言程序设计
5
C54x的软件开发需要借助于TI公司提供的软件开发工具:编译器、汇编器和连接器,另外还有一些辅助的软件包,如归档器、列表器和代码转换器等。
第4章 汇编语言程序设计 C54x的软件开发需要借助于TI公司提供的软件开发工具:编译器、汇编器和连接器,另外还有一些辅助的软件包,如归档器、列表器和代码转换器等。 这些软件开发工具都被集成在CCS(Code Composer Studio)开发环境中。将在第6章详细介绍CCS的组成及其使用方法
6
第4章 汇编语言程序设计 C源文件 C编译器 汇编 源文件 汇编器 COFF 目标文件 链接器 可执行的 COFF文件 宏源文件 存档器
宏库 目标 文件库 建库工具 运行时 支持库 EPROM 编程器 交叉引用 列表器 调试工具 TMS320C54x 绝对地址 HEX代码 转换工具
7
4.2 公共目标文件格式COFF COFF: common object file format
汇编器和链接器生成的目标文件,是一个可以由C54x器件执行的文件。这些目标文件的格式称之为公共目标文件格式(COFF)。 采用这种文件格式的优点是: 将指令和数据按照段的概念进行组织和存储,这使得程序的可读性大大增强,更容易编写程序,更便于进行程序的移植,更利于进行模块化的程序设计,为管理代码段及系统存储器提供了灵活的方法和手段。
8
COFF文件有3种类型:COFF0、COFF1、COFF2
链接器能够读/写所有类型的COFF文件, C54x默认时链接器生成的是COFF2文件,采用-v n链接选项可以选择不同类型的COFF文件。
9
4.2.1分段结构 所谓“段”就是在存储器映像中占据连续空间的一段独立的代码或数据。每个目标文件都分成若干段。
COFF目标文件包含以下三个默认的段: .text 段:通常内含可执行代码; .data段:通常内含已初始化数据; .bss段:是为没有初始化的数据保留空间的。 COFF目标文件的段又可分为两大基本类型:已初始化段和未初始化段。
10
4.2.1分段结构 Section(“段”)概念:一块连续的储存空间,可存放程序或数据
在编程时,“段”没有绝对定位,每个“段”都认为是从0地址开始的一块连续的储存空间,而无需关心这些“段”究竟定位在系统的哪些地方。 优点:便于程序的模块化编程;便于工程化管理:可将软件开发人员和硬件开发人员基本上分离开。 重定位:由于所有的“段”都是从0地址开始,所以程序编译完成后是无法运行的,要让程序正确运行,必须对“段”进行重新定位,这个工作由链接器完成。 .cmd文件:MEMORY命令描述系统硬件资源,SECTIONS命令描述软件人员程序中用到的“段”如何定位到恰当的硬件资源上。
11
4.2.1分段结构 1.已初始化段 包含程序代码、常数表格和数据。已初始化段的值是不可修改的,因而一般将它们建立在程序存储器中。
每个段都可以独立的进行重定位,且可访问在其它段中定义的符号。 主要有: .text段——已初始化段; .data段——已初始化段; .sect段——已初始化段,由汇编器伪指令建立的自定义段。
12
4.2.1分段结构 2.未初始化段 是为变量在数据存储器中保留空间的。它们在目标文件中没有实际内容,只是保留出空间,在运行程序时再利用这些空间去建立和存储变量。 未初始化段一般应建立在片内或片外RAM中。 由这些段定义的空间仅作为临时存储空间,在程序运行时,可以利用这些存储空间存放变量。 未初始化段分为默认的和命名的两种,分别由汇编器伪指令.bss和.usect产生。.
13
4.2.1分段结构 重定位 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
14
4.2.1分段结构 3. 段定义伪指令 汇编器对段的处理是通过段伪指令来区别各个段的,并将段名相同的语句汇编在一起。
汇编器有5条伪指令可识别汇编语言程序的各个部分: ● .bss ● .usect ● .text ● .data ● .sect ——定义未初始化段 ——定义已初始化段
15
4.2.1分段结构 定义已初始化段的伪指令 .text [段起点] .data [段起点] .sect “段名”[,段起点]
段起点——是任选项。 若选用,它为段程序计数器SPC定义一个起始值。 若默认,则SPC从0开始。
16
定义未初始化段的伪指令 (1) .bss伪指令: 用于在bss段中保留若干个空间。格式:
符号—对应于保留的存储空间第一个字的变量名称。 字数—表示在bss段或标有名字的段中保留若干个存储单元。 块标记—若非零值,则分配的字数空间连续,除非大于一页,否则不跨页。 定位标记—表明字的对齐方式(C54x偶地址对齐) 每调用一次.bss伪指令,汇编器在相应的段保留更多的空间。
17
4.2.1分段结构 定义未初始化段的伪指令 (2) .usect伪指令 用于为指定的命名段保留若干个空间。格式:
.bss 符号, 字数 [, [块标记][, 定位对齐标记]] 建立一个自定义段但是没有初始化的段,在自定义的段中保留空间。 每调用一次.usect伪指令,汇编器在指定的命名段保留更多的空间。
18
4.2.1分段结构 例4-1:段定义程序举例。 .text .word 1,2,3,4,5,6,7,8 .data
.sect “var1” .word ,18 .bss x1, 19 ;为.bss段保留19个字单元空间。 y1 .usect “var2”, 40; 为var2段保留40个单元空间。
19
例4-1:段定义程序举例。 程序建立了5个段,情况如下: .text .word 1,2,3,4,5,6,7,8 .data .word 9,10,11,12 .word ,14 .word ,16 .sect “var1” .word ,18 .bss x1,19 ; y1 .usect “var2”, 40; .text段: 8个16位字1~8。 .data段: 8个16位字9~16。 Var1段: 2个16位字17, 18。 .bss段: 保留19个字连续空间, 首单 元的标号是x1。 Var2段: 保留40个字连续空间, 首单元的标号是y1。
20
4.2.2 汇编器对段的建立 当汇编器遇到.text或.data或.sect命令时,将停止对当前段的汇编(相当于一条结束当前段汇编的命令),然后将紧接着的程序代码或数据汇编到指定的段中,直到再遇到另一条.text、.data或.sect命令为止。 ;初始化文本段 ;1字指令(DP直接寻址) ;2字指令 .text Add: LD 0Fh, A Aloop: SUB #1, A BC Aloop, AGEQ .data ivals .word 0AAh,0BBh,0CCh ;初始化数据段 ;3组数据放入.data段
21
4.2.2 汇编器对段的建立 当汇编器遇到.bss或.usect命令时,并不结束当前段的汇编,只是暂时从当前段脱离出来,并开始对新的段(.bss或.usect)进行汇编,结束后仍在离开时的段。 .data coeff .word 011h,022h,033h .bss buffer,10 prt .word 0123h .text Add: LD 0Fh, A Aloop: SUB #1, A BC Aloop, AGEQ ;初始化数据段 ;3组数据放入.data段 ;在.bss段保留10个单元 ;.bss后0123h仍然在.data段 ;初始化文本段 ;1字指令(DP直接寻址) ;2字指令
22
4.2.2 汇编器对段的建立 段程序计数器SPC 汇编器为每个段都安排了一个单独的程序计 数器称之为段程序计数器SPC。
SPC表示在程序代码或数据段内当前的地址。 开始时汇编器将每个SPC置0。当汇编器将程序 代码或数据加到段内时,增加相应的SPC值。若 再继续对某个段汇编,则相应的SPC就在先前的 数值上继续增加。
23
例4-2 段定义应用举例 汇编语言源程序: .data coeff .word 011h,022h,033h .bss buffer,10
例4-2 段定义应用举例 汇编语言源程序: .data coeff .word 011h,022h,033h .bss buffer,10 prt .word 0123h .text Add: LD 0Fh, A Aloop: SUB #1, A BC Aloop, AGEQ ivals .word 0AAh,0BBh,0CCh ;初始化数据段 ;3组数据放入.data段 ;在.bss段保留10个单元 ;.bss后0123h仍然在.data段 ;初始化文本段 ;1字指令(DP直接寻址) ;2字指令 ;初始化数据段 ;3组数据放入.data段
24
汇编语言源程序: var2 .usect “newvars”, 1 ;在newvars段保留7个单元
;初始化文本段 ;1字指令(DP直接寻址) ;2字指令 var2 .usect “newvars”, 1 inbuf .usect “newvars”, 7 .text Mpy: LD 0Ah, B Mloop: MPY #0Ah, B BC Mloop, BNOV .sect “vectors” .word 011h,033h ;建立vectors命名段 ;2组数据放入vectors命名段
25
例4-2 段定义应用举例 汇编语言源程序经过汇编后,共建立了5个段: .text段——文本段,段内有10个字可执行的程序代码
例4-2 段定义应用举例 汇编语言源程序经过汇编后,共建立了5个段: .text段——文本段,段内有10个字可执行的程序代码 .data段——已初始化的数据段,段内有7个字的数据 vectors段——用.sect命令生成的命名段,段内有2个字 的初始化数据 .bss段——未初始化的数据段,在存储器中为变量保留 10个存储单元 newvars段——用.usect命令建立的命名段,为变量保 留8个存储单元
26
例4-2 经汇编后,得列表文件(.lst): 汇编设置: 汇编语言源程序 源程序的行号
(空行) ********************************** ** 汇编一个初始化表到.data段 ** ********************************** data coeff .word 011h,022h,033h ********************************** ** 在.bss段中为变量保留空间 ** ********************************** bss buffer,10 ********************************** ** .bss结束后仍然在.data 段中 ** ********************************** prt word h 汇编设置: Project→Build Options…→Compiler →Category(Assembly) → Generate Assembly Listing Files(al)
27
例4-2 经汇编后,得列表文件(.lst): 源程序的行号 段程序 计数器 目标 代码 汇编语言 源程序 1 (空行)
(空行) ********************************** ** 汇编一个初始化表到.data段 ** ********************************** data coeff .word 011h,022h,033h ********************************** ** 在.bss段中为变量保留空间 ** ********************************** bss buffer,10 ********************************** ** .bss结束后仍然在.data 段中 ** ********************************** prt word h
28
源程序的行号 段程序 计数器 目标 代码 汇编语言 源程序 15 **********************************
********************************** ** 汇编代码到.text段 ** ********************************** text f add: LD Fh,A ;DP直接寻址 f010 aloop: SUB #1, A f BC aloop,AGEQ ’ (’ : relocatable internal reference) ********************************** ** 汇编另一个初始化表到.data段 ********************************** data aa ivals .word 0AAh,0BBh,0CCh bb cc ********************************** ** 为更多的变量定义另一个段 ** ********************************** var usect “newvars”,1 inbuf .usect “newvars”,7
29
例4-2 经汇编后,得列表文件( .lst ): 源程序的行号 段程序 计数器 目标 代码 汇编语言 源程序
**************************************** ** 汇编更多代码到.text段 ** **************************************** text a mpy: LD Ah,B f166 mloop MPY #0Ah,B a f BC mloop,BNOV ’ (’ : relocatable internal reference) **************************************** 为中断向量.vectors定义一个自定义段 **************************************** sect “vectors” word h,033h 源程序的行号 段程序 计数器 目标 代码 汇编语言 源程序
30
例4-2 经汇编后,共建立了5个段: SPC 行号 目标代码 行号 目标代码 段名 .text 6 0011 .data 6 0022 6
100f f010 0001 f842 110a f166 000a F868 0006 0011 0022 0033 0123 00aa 00bb 00cc 没有数据 保留8个字 .text ******************************* ** 汇编一个初始化表到.data段 ** ******************************* data coeff .word 011h,022h,033h ******************************* ** 在.bss段中为变量保留空间 ** ******************************* bss buffer,10 ******************************* ** 仍然在.data 段中 ** ******************************* prt .word h data coeff .word 011h,022h,033h 6 0011 .data 6 0022 6 0033 14 0123 bss buffer,10 vectors .bss 10 没有数据 保留10个字 prt .word h newvars
31
SPC 第4章 汇编语言程序设计 目标代码 行号 .text .data .data .bss newvars
段名 100f f010 0001 f842 0001’ 110a f166 000a F868 0006‘ 6 14 0011 0022 0033 0123 00aa 00bb 00cc .data 10 没有数据 保留10个字 .bss ******************************** ** 汇编代码到.text段 ** ******************************** text f add: LD Fh,A f010 aloop: SUB #1, A f BC aloop,AGEQ ’ ********************************** ** 汇编另一个初始化表到.data 段 ** ********************************** data aa ivals .word 0AAh,0BBh,0CCh bb cc ******************************** ** 为更多的变量定义另一个段 ** ******************************** var2 .usect “newvars”,1 inbuf .usect “newvars”,7 19 .text 100f 20 f010 20 0001 text 21 f842 f add: LD Fh,A 21 0001’ f010 aloop: SUB #1, A f BC aloop,AGEQ ’ (’ : relocatable internal reference) .data data 26 00aa 26 00bb aa ivals .word 0AAh,0BBh,0CCh bb cc 26 00cc var2 .usect “newvars”,1 newvars inbuf .usect “newvars”,7 30 保留1个字 31 保留7个字
32
SPC 第4章 汇编语言程序设计 目标代码 行号 .text .data vectors .bss newvars
段名 19 20 21 100f f010 0001 f842 0001’ 110a f166 000a F868 0006 .text 6 14 26 0011 0022 0033 0123 00aa 00bb 00cc .data 0044 0088 10 没有数据 保留10个字 .bss 30 31 保留8个字 newvars .text ********************************* ** 汇编更多代码到.text段 ** ********************************* text a mpy: LD Ah,B f166 mloop MPY #0Ah,B a f BC mloop,BNOV ’ **************************************** ** 为中断向量.vectors定义一个自定义段 ** **************************************** sect “vectors” word h,033h 36 110a 37 f166 text 37 000a 38 f868 a mpy: LD Ah,B 38 0006’ f166 mloop MPY #0Ah,B a f BC mloop,BNOV ’ (’ : relocatable internal reference) vectors 43 0011 43 0033 sect “vectors” word h,033h
33
4.2 公共目标文件格式COFF 4.2.3 连接器对段的处理
链接器是开发’C54x器件必不可少的开发工具之一,连接器对段的处理主要完成两个功能: 把1个或多个目标文件(文件名.obj)连接起来,产生可执行的COFF输出文件(文件名.out)。 按照目标系统的需要配置存储器,并将符号和段重新定位,确定输出文件的存储器地址。 One of the linker’s functions is to relocate sections into the target memory map, this function is called allocation.
34
4.2.3 连接器对段的处理 定位(Allocation): 连接器将.text、.data、.bss等段存放到硬件系统的存储空间中去,这就是定位。 连接器有两种定位的方法: 缺省定位,是指连接器对各段的定位是固定不变的方式; 存储器映射定位,在连接前,使用连接器的伪指令MEMORY和SECTIONS等编写一个命令文件,定义出存储区域,然后,由连接器去进行存储区的映像定位。
35
4.2.3 连接器对段的处理 1. 存储器映射定位 a.obj b.obj c.obj /* Input filenames */
-0 prog.out -m prog.map /* Options */ 1. 存储器映射定位 用户编写的命令文件由下列4部分组成: 1)输入文件名,用来指定目标文件、归档库文件或其它命令文件。 2)连接器选项。这些选项可以编写在命令文件中,也可以使用CCS的选项或命令行实现。 MEMORY /* MEMORY directive */ { ROM: origin = 01000h length = 0100h PAGE 1: RAM: origin = 100h length = 0100h } SECTIONS /* SECTIONS directive */ { .text: > ROM .data: > ROM .bss: > RAM 3)连接器的伪指令MEMORY和SECTIONS。MEMORY指出目标存储器的配置;SECTIONS控制段的构成及其地址的分配。 4)赋值说明,用来给全局符号定义和赋值。
36
4.2.3 连接器对段的处理 2. 连接器的两个主要伪指令 MEMORY伪指令——用来定义目标系统的存储器配置空间,包括对存储器各部分命名,以及规定它们的起始地址和长度。 SECTIONS伪指令——用来指定链接器将输入段组合成输出段方式,以及输出段在存储器中的位置,也可用于指定子段。 若未使用伪指令,则连接器将使用目标处理器默认的方法将段放入存储空间。
37
4.2.3 连接器对段的处理 2. 连接器的两个主要伪指令 1)MEMORY命令 MEMORY用来定义目标系统的存储器。它的语法如下:
{ PAGE 0 : name 1 [(attr)] : origin = constant , length = constant; PAGE n : name n [(attr)] : origin = constant , length = constant; } PAGE 0 : PROG: origin = 0x0080, length = 0xFF00 PAGE 1 : DATA: origin = 0x0080, length = 0xFF80 attr属性: [R可读; W可写;X可执行;I可初始化],默认全有。
38
2. 连接器的两个主要伪指令 2)SECTIONS命令
SECTIONS用来告诉连接器怎样组合输入段以及在存储器的何处存放输出段。在MEMORY指定了一种存储模式后,就应使用SECTIONS去定位。 (An output section is a section in the output file.) SECTIONS的一般语法如下: SECTIONS { name : [property, property, property,...] } .text: PAGE = 0 .data: PAGE = 0 .bss: PAGE = 1 .text: PAGE = 0 .data: PAGE = 0 .bss: PAGE = 1
39
SECTIONS {name : [property, property, property,...]
name指定输出文件中的输出段名(.text, .data等), 该名称不能任意指定,而是在汇编器中已经指定的段名。 property定义段的内容以及指明它是怎样被分配的。 property主要有下列几种: ☆ load定义该段装载至某存储区域,Syntax: load = allocation or allocation or > allocation 例:load=ROM 或 load=0FF80h 或 ROM 或 > ROM ☆ run 定义该段的运行存储器区域 ,Syntax: run = allocation or run > allocation 例: run >RAM 或 run=800h
40
SECTIONS {name : [property, property, property,...]
input sections指出构成输出段的输入段 Syntax: { input_sections } 例:.text : { f1.obj(.text) f2.obj(sec1) } Section type段的类型, 定义特殊段的标志 , Syntax: type = COPY or type = DSECT or type = NOLOAD Fill value用来为没有初始化的空单元填充数值 fill = value or name: ... { ... } = value
41
例4-3 命令文件举例 filename.cmd a.obj b.obj c.obj /* Input filenames */
-0 test.out -m test.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
42
4.2.3 连接器对段的处理 3. 缺省定位(默认定位) 链接器可对多个目标文件进行链接。若链接文件中不使用MEMORY和SECTIONS命令,则为默认方式。 若采用默认链接,链接器将对多个目标文件中的各个段进行组合,形成各自的对应段,并将各个段配置到所指定的存储器中,形成可执行的目标模块。 在默认的方式下,链接器将从存储器的0080h开始,对组合后的各段进行存储器配置。
43
4.2.3 连接器对段的处理 例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
44
4.2.3 连接器对段的处理 在这种缺省定位方式下,默认的存储器分配:
① 将所有.text段组合在一起,形成一个.text 段,并分配到程序存储器中; ② 将多个目标文件中的.data段组合在一起, 分配到紧接着.text段的程序存储空间中; ③ 将.bss段组合,配置到数据存储器中; ④ 自命名段。初始化的命名段按顺序分配到紧 随.data段的程序存储器,而未初始化命名段将被配 置到紧随.bss段的数据存储器中。
45
4.2.3 连接器对段的处理 File1.obj .text1 .data1 .bss1 table_1 u_vars1 .text1
(初始化的命名段) u_vars1 (未初始化的命名段) 程序存储器 数据存储器 .text1 没有配置 .text .text2 .data1 .data .data2 .bss1 .bss table_1 .bss2 u_vars1 table table_2 File2.obj .text2 .data2 .bss2 table_2 (初始化的命名段) u_vars2 (未初始化的命名段) FFT u_vars1 u_vars2 FFT FFT 没有使用 没有使用 没有配置
46
4.3 汇编器的伪指令 汇编器伪指令仅在汇编过程中起作用,为汇编器提供一些控制和管理信息及功能,但并不产生目标代码。
汇编器伪指令可完成以下工作: .text: .data: .bss: .word 将代码和数据汇编进指定的段 为未初始化的变量在存储器中保留空间 初始化存储器(.word,.byte, .long .... ) 控制清单文件是否产生 汇编条件代码块 定义全局变量 为汇编器指定从中可以获得宏的库 考察符号调整信息
47
4.3 汇编器的伪指令 下面主要介绍以下几类汇编伪指令: ⑴ 段定义伪指令 如.bss、.data、.sect、.text、.usect等。
⑵ 对常数(数据和存储器)进行初始化的伪指令 如.bes、.byte、.field、.float、.int、.long、.space、.string、.pstring、.xfloat、.xlong、.word等。
48
4.3 汇编器的伪指令 ⑶ 调整SPC的指令 如.align等。 ⑷ 格式化输出清单文件的伪指令 如.drlist、.drnolist等。
⑸ 引用其他文件的伪指令 如.copy、.def、.global、.include、.mlib、 .ref等。 (6) 定义宏的伪指令 如.macro等
49
4.3 汇编器的伪指令 (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等。
50
4.3 汇编器的伪指令 1.段定义伪指令 段定义伪指令为汇编器提供分段信息。 助记符及语法格式 说 明
说 明 .bss symbol, size in words [,blocking] [, alignment] 为未初始化的数据段.bss保留存储空间。 .data 指定.data后面的代码为数据段,通常包含初始化的数据。 .sect “section name” 设置自定义已初始化段 .text 指定.text后面的代码为文本段,通常包含可执行的代码。 symbol .usect “section name”, size in words [,blocking] [,alignment flag] 为未初始化的命名段保留空间。类似.bss伪指令,但允许保留与.bss段不同的空间。
51
2.初始化常数的伪指令 :用于为当前的段汇编常数值 LABLE . space 6*16 LABLE . bes 6*16 助记符及语法格式
说 明 .byte value [,…, value] 初始化当前段里的一个或多个连续字。每个值的宽度被限制为8位。即把8位的值放入当前段的连续字。 .char value [,…, value] .field value [,size in bits] 初始化一个可变长度的域。将单个值放入当前字的指定位域中。 . space size in bits 在当前段保留一定数量的位数, 当与标号连用时,标号指向保留的第一个字。 . bes size in bits 在当前段保留一定数量的位数, 当与标号连用时,标号指向保留的最后一个字。 LABLE . space 6*16 LABLE . bes 6*16
52
2.初始化常数的伪指令 助记符及语法格式 说 明 .int value [,…,value]
说 明 .int value [,…,value] 初始化一个或多个16位整数。即把16位的值放到当前段的连续的字中。 .half value [,…,value] 初始化一个或多个16位整数。 .short value [,…,value] .word value [,…,value] .long value [,…,value] 初始化一个或多个32位整数。即把32位的值放到当前段的2个连续的字中。自动对准长字边界。 .xlong value [,…,value] 初始化一个或多个32位整数。即把32位的值放到当前段的2个连续的字中。不自动对准长字边界。 .string “string” [,…, “string”] 初始化一个或多个字符串。把8位字符从一个或多个字符串放进当前段。
53
2.初始化常数的伪指令 :用于为当前的段汇编常数值 助记符及语法格式 说 明 .float value [,…, value]
说 明 .float value [,…, value] 初始化一个或多个IEEE的单精度(32位) 浮点数,自动对准长字边界. .xfloat value [,…, value] 初始化一个或多个IEEE的单精度(32位) 浮点数, 并将它保存在当前段的两个连续字中。不自动对准长字边界。 .double value [,…,value] 初始化一个或多个双精度(32位) 浮点数。即计算浮点数的单精度(32位) 浮点表示, 并将它存储在当前段的2个连续的字中。该伪指令自动对准长字边界。 .xdouble value [,…,value] 初始化一个或多个双精度(32位) 浮点数。即计算浮点数的单精度(32位) 浮点表示, 并将它存储在当前段的2个连续的字中。该伪指令不必对准长字边界。
54
【例4.5】比较.byte,.int,.long,.xlong,.float,.xfloat,.word和.string伪指令。
aa .byte 0AAh, 0BBh bb ccc .word 0ccch eee .xlong 0EEEEFFFh efff eeee .long 0EEEEFFFFh ffff dddd .int 0DDDDh fff .xfloat 00000a ffac c 3fff .float 00000d ffac e string “help” 00000f 0065 c
55
.field伪指令将单个值放入当前字的指定位域。该伪指令可将多个字段或域打包成单个字, 直到字被填满, 汇编器不增加SPC。
例 数值 位数 field 3, 3 field 8, 6 field 16, 5 field h,20 field h,32
56
4.3 汇编器的伪指令 3. 对齐段程序计数器SPC的伪指令 对齐段程序计数器的伪指令包括:.align伪指令和.even伪指令。
助记符及语法格式 说 明 .align [size in words] 用于将段程序计数器(SPC)对准在1~128字(必须是2的乘方)的边界。 .even 用于使SPC指到下一个长字的边界(偶字边界)。相当于 .align 2
57
4.3 汇编器的伪指令 3. 对准段程序计数器SPC的伪指令 .align伪指令的操作数必须是在20~27之间且等 于2的幂。 例:
58
4. 格式化输出清单文件的伪指令 助记符及语法格式 说 明 .drnolist 用于抑制某些伪指令在清单文件中的出现。 .drlist 允许.drnolist抑制的伪指令在清单文件中重新出现。 .fclist 允许按源代码在清单文件中列出条件为假的代码块。汇编器默认状态。 false conditional code block listing .fcnolist 只列出实际汇编的条件为真的代码块。 .length page length 调节清单文件输出页面的长度。可针对不同的输出设备灵活调节输出页面的长度。 .list 允许汇编器将所选择的源语句输出到清单文件。 .nolist 禁止汇编器将所选择源语句输出到清单文件。
59
.option {B│L│M│R│T│W│X} 用于控制清单文件的某些功能。 {B|L|T|W}
4. 格式化输出清单文件的伪指令 续表 助记符及语法 说 明 .mlist 允许列出所有的宏扩展和循环块。 .mnolist 禁止列出所有的宏扩展和循环块。 .option {B│L│M│R│T│W│X} 用于控制清单文件的某些功能。 {B|L|T|W} 将.byte,.long,.string, .word伪指令的列表限制在一行 {R} 复位B, M, T, W 的选项限制. {M} 在清单文件中关闭宏扩展. {X} 产生符号交叉引用列表文件(也可在用汇编命令时用选项 -x )
60
5. 引用其它文件的伪指令 这类伪指令为引用其它伪指令提供信息。 伪指令及语法 说明 .copy [”]filename[”] 通知汇编器从其它文件中读取源代码语句,并出现在清单文件中 .include [”]filename[”] 通知汇编器从其它文件中读取源代码语句,但不出现在清单文件中 .def symbol1 [, ... , symboln] 在当前模块中定义的符号,在其它模块中可以使用 .ref symbol1 [, ... , symboln] 在其它模块中定义的符号,在当前模块中可以使用 .global symbol1 [, ... , symboln] 声明符号为全局符号,使其在连接时可被其它模块使用
61
4.3 汇编器的伪指令 6. 定义宏的伪指令 常用的定义宏的伪指令: 伪指令及语法 说明 .macro 定义宏
.mlib [“]filename[”] 定义宏库 .mexit 相当于一条goto .endm语句。当确定宏展开将失败时,使用该伪指令 .endm 结束宏代码块 .var 定义一个局部的宏替代符号
62
4.3 汇编器的伪指令 6. 定义宏的伪指令 如果程序中有一段程序需要执行多次,就可以把这一段程序定义(宏定义)为一条宏指令,然后在需要重复执行这段程序的地方调用这条宏指令(宏调用)。 宏的使用需要下列3个步骤: ☆ 宏定义: 在调用宏时,必须首先定义宏; ☆ 宏调用: 在定义宏之后,可在源程序中调用宏; ☆ 宏扩展: 在源程序调用宏指令时,汇编器将对宏指令进行扩展。
63
6. 定义宏的伪指令 1). 宏定义 在调用宏时,必须首先定义宏。有两种方法定义宏:
可在源文件的开始定义宏,或者在.include或.copy的文件中定义; 在宏库中定义。 宏库——是由存档器以存档格式产生的文件集。 宏库中的每一成员包含一个与成员对应的宏定义。可通过.mlib指令访问宏库。 .mlib [”]filename[”]
64
6. 定义宏的伪指令 add3 .macro P1, P2, P3, ADDR;宏定义ADDR = P1 + P2 + P3 ;宏名称add3 1). 宏定义 宏定义的格式: macname .macro [parameter 1][, …, parameter n] 宏程序语句或宏伪指令 [.mexit] .endm LD P1, A;宏程序语句 ADD P2, A ADD P3, A STL A, ADDRP macname: 宏程序名称,必须放在源程序标号域。 .macro: 声明该语句为宏定义的第一行伪指令。 parameters: 任选替代参数,作为宏指令的操作数。 宏程序语句: 每次宏调用时要执行的指令或汇编命令。 宏伪指令: 用于控制宏指令展开的命令。 .mexit: 相当于一条跳到.endm语句。 .endm: 结束宏定义。
65
6. 定义宏的伪指令 1). 宏定义的注释 macname .macro [parameter 1][, …, parameter n]
宏程序语句或宏伪指令 [.mexit] .endm 如果希望在宏定义中包含有注释,但又不希望这些注释出现在扩展宏中,可在注释前面加上感叹号“!”。 如果希望这些注释出现在扩展宏中,需在注释前面加上符号“*”或“;”。
66
6. 定义宏的伪指令 2). 宏调用 在定义宏之后,可在源程序中使用宏名进行宏调用。 宏调用的格式:
add3 .macro P1, P2, P3, ADDR;宏定义ADDR = P1 + P2 + P3 …… ;宏名称add3 2). 宏调用 在定义宏之后,可在源程序中使用宏名进行宏调用。 宏调用的格式: [label][:] macname [parameter 1][,…,parameter n] 任选的替代参数 数目应与宏指令定义的相等 标号 任选项 宏名称 位于操作码区 add3 abc, def, ghi, adr;宏调用,替代参数4个 ;adr = abc +def +ghi
67
6. 定义宏的伪指令 3). 宏扩展 若源程序中调用宏指令,则汇编时对宏指令进行扩展。
扩展时汇编器先将变量传递给宏参数,按宏定义取代 调用宏语句,然后再对源代码进行汇编。 在默认的情况下,扩展宏将出现在清单文件中,若不需 要扩展宏出现在清单文件中,则可通过伪指令.mnolist 来实现。 add3 .macro P1, P2, P3, ADDRP;宏定义,宏名称add3 LD P1, A ;宏程序语句 ADD P2, A ADD P3, A STL A, ADDRP .endm ;宏结束 …… add3 abc, def, ghi, adr;宏调用,参数是全局变量 LD abc, A ;汇编时的宏展开 ADD def, A ADD ghi, A STL A, adr ! ! ! ! ! undefined external reference
68
4.3 汇编器的伪指令 6. 定义宏的伪指令 当汇编器遇到宏定义时,将宏名称放进操作码 表中,并将重新定义前面已经定义过的与之具有相 同名称的宏、库成员、伪指令或指令助记符。 用这种方法可以扩展指令和伪指令的功能以及 加入新的指令。
69
4.3 汇编器的伪指令 例4-6 宏定义、调用和扩展举例。 1 * add3 2 * ADDRP = P1 + P2 + P3
3 add3 .macro P1, P2, P3, ADDRP;宏定义,宏名称add3 LD P1, A ;宏程序语句 ADD P2, A ADD P3, A STL A, ADDRP endm ;宏结束 9 global abc, def, ghi, adr 11 add3 abc, def, ghi, adr;宏调用,替代参数4个
70
1: LD Smem, dst 1: ADD Smem, src 嵌套层数 1: STL src, Smem
add3 abc, def, ghi, adr;宏调用 ;汇编时的宏展开 ! LD abc, A ! ADD def, A ! ADD ghi, A ! STL A, adr 1: LD Smem, dst 1: ADD Smem, src ! undefined external reference ’ .text relocatable internal reference ” .data relocatable + .sect relocatable - .bss, .usect relocatable % complex relocation expression 嵌套层数 relocation type 1: STL src, Smem the assembler assumes all undefined external symbols have values of 0 relocation
71
7. 条件汇编伪指令 用来通知汇编器按照表达式计算出的结果的真假,决定是否对某段代码进行汇编。 有两组伪指令用于条件代码块的汇编: (1) .if/.elseif/.else/.endif伪指令 用于通知汇编器按照表达式的计算结果,对某段代码块进行条件汇编。要求表达式和伪指令必须完全在同一行指定。 (2) .loop/.break/.endloop伪指令 用于通知汇编器按照表达式的计算结果重复汇编一个代码块。
72
7. 条件汇编伪指令 助记符及语法格式 说 明 .if well-defined expression
说 明 .if well-defined expression 标记条件块的开始。仅当.if条件为真时,对紧接着的代码块进行汇编。 .elseif well-defined expression 若.if条件为假,而.elseif条件为真时,对紧接着的代码块进行汇编。 .else well-defined expression 若.if条件为假,对紧接着的代码块进行汇编。 .endif 标记条件代码块的结束,并终止该条件代码块。 .loop [well-defined expression] 按照表达式确定的次数进行重复汇编的代码块的开始。表达式是循环的次数。 .break [well-defined expression] 若.break表达式为假,通知汇编器继续重复汇编;而当表达式为真时,跳到紧接着 .endloop后面的代码。 .endloop 标记代码块的结束。
73
汇编时间符号伪指令将符号与常数值或字符串进行等价。 伪指令及语法 说明
8. 汇编时间符号伪指令 汇编时间符号伪指令将符号与常数值或字符串进行等价。 伪指令及语法 说明 .asg [“]character string [”], substitution symbol 将一个字符串赋给替代符号,并存在替代表中,替代符号可以重新定义 .eval well-defined expression, substitution symbol 计算一个表达式,将其结果转换成字符,并将字符串赋给替代符号 symbol .equ value 例如:INDEX .equ 100 给符号赋值,符号存在符号表中,不能被重新定义 symbol .set value 例如:INDEX .set 100 给符号赋值,符号被存在符号表中,不能被重新定义 .set和.equ等效
74
8. 汇编时间符号伪指令 伪指令及语法 说明 .label symbol 定义一个特殊的符号,用来指出在当前段内的装载时的地址
.struct 设置类似C的结构定义 .endstruct 结束结构体 .union 建立类似C的union(联合)定义 .endunion 结束union(联合) .tag 给类似C的结构表赋上一个符号 .struct和.endstruct用来设置类似C的结构定义,只是产生一个可重复使用的符号模板,而不分配存储器。 .tag将结构体与一个标号联系起来,.tag伪指令不分配存储器,且结构体的标记符必须在使用之前先定义好。
75
8. 汇编时间符号伪指令 汇编时间符号伪指令.struct 举例:允许把几个(不同的)数据类型元素组合在一起,产生新的数据类型。 例4-7 伪指令.struct和.endstruct的使用。 type struct ; 结构标记符(type)定义 X long Y int T_LEN .endstruct COORD .tag type ;声明COORD为结构实例 .bss COORD, T_LEN; 实际的存储器配置 ;ADD COORD.Y, A ; 直接寻址,设置DP;易出错 可使用 ADD *(COORD.Y) , A; 绝对寻址
76
8. 汇编时间符号伪指令 .union/.endunion伪指令通过创建符号模板,提供在相 同的存储区域内管理多种不同的数据类型的方法。 .union不分配存储器,只产生可重复使用的符号模板。 .tag伪指令将union属性与一个标号联系起来,将标号 声明为一个已经定义好的联合union。 通过.bss给声明的union标号分配存储空间,它允许类 型和大小不同的数据临时地存储在相同存储器空间。 xample .union; union标记符 ival word ; union 成员1,1个字长16位 fval float ; union 成员2,2个字长32位 real_len .endunion; real_len = 2 所有成员最长的数据长度 employid .tag xample ; 声明标号employid 为union .bss employid, real_len ;分配存储空间 ADD *(employid.fval), A ; 使用绝对寻址
77
8. 汇编时间符号伪指令 union是第一个结构成员 当union没有标记符时,它的所有成员都将进入符号 表,每一个成员有唯一的名称。
s2_tag .struct ;结构标记符定义 .union ;无标记符 h half h uhalf w word .endunion w word ;第二个结构成员 s2_len .endstruct XYZ tag s2_tag ;声明结构的实例 .bss XYZ, s2_len ;分配存储空间 ADD *(XYZ.h2), A ; union的引用 union是第一个结构成员
78
例4-8 .union/.endunion伪指令举例。
.data s2_tag .struct ;结构标记符定义 .union ;union是第一个结构成员 .struct ;结构是union成员 h half h uhalf .endstruct w word ;字w1是另一个union成员 .endunion w word ;第二个结构成员 s2_len .endstruct XYZ tag s2_tag ;声明结构的实例instance .bss XYZ, s2_len ;分配存储空间 .text ADD *(XYZ.h2), A ; ADD XYZ.h2, ; DP设置不好直接寻址易错 ;h1, h2和w1存在于相同的存储器中
79
9.混合伪指令 常用的混合伪指令: 助记符及语法格式 说 明 .end 终止汇编,位于程序源程序的最后一行。 .far_mode
说 明 .end 终止汇编,位于程序源程序的最后一行。 .far_mode 通知汇编器调用为远调用。 .mmregs 为存储器映像寄存器定义符号名。使用.mmregs的功能和对所有的存储器映像寄存器执行.set伪指令相同。 .newblock 用于复位局部标号。 .version [value] 确定运行指令的处理器,每个’C54x器件都有一个与之对应的值。 .emsg string 把错误消息送到标准的输出设备。 .mmsg string 把汇编时间消息送到标准的输出设备。 .wmsg string 把警告消息送到标准的输出设备。
80
4.3 汇编器的伪指令 9.混合伪指令 .newblock伪指令用于复位局部标号。
局部标号是形式为$n或name?的符号。当它们出现在标号域时被定义。局部标号可用作跳转指令的操作数的临时标号。 .newblock伪指令通过在它们被使用后将它们复位的方式来限制局部标号的使用范围。
81
4.3 汇编器的伪指令 9.混合伪指令 有3个伪指令可以允许用户定义自己的错误和警告消息:
.emsg伪指令以和汇编器同样的方式产生错误,增加错误的计数并防止汇编器产生目标文件。 .wmsg伪指令的功能与.emsg伪指令相似,但它增加警告计数,而不增加错误计数。它也不影响目标文件的产生。 .mmsg伪指令的功能与.emsg和.wmsg伪指令相似,但它不增加错误计数或警告计数。也不影响目标文件的产生。
82
4.4 C54x汇编语言的有关知识 汇编语言是一种面向CPU指令系统的低级语言。汇编语言源程序中包含汇编语言指令Assembly Language Instructions 、汇编伪指令Assembler Directives、宏伪指令Macro Directives和一些规定的数字、字符、符号地址及表达式等。 下面讨论C54x汇编语言源程序的有关知识,包括汇编语言源程序的格式,各种数字、符号和表达式的规定;汇编伪指令的使用;汇编器、连接器的调用方法和选项等。
83
4.4 C54x汇编语言的有关知识 4.4.1 汇编语言源程序的格式
助记符指令语法格式: [标号][:] 助记符 [操作数] [; 注释] 例4-9 指令格式举例。 x set H ; 符号x=200H Begin: STM #x,AR1 ; 将200H加载到AR1 STL A, *AR ;(A)→(AR1) 标 号 助记符 操作数 注 释
84
4.4.1 汇编语言源程序的格式 语句的书写规则: ①所有语句须以标号、空格、星号或分号(*或;)开始;
②标号可选,若使用标号,则标号必须从第一列开始; ③所有包含汇编伪指令的语句必须在一行完成指定; ④各部分之间必须用空格分开,Tab字符与空格等效; ⑤注释可选。若注释在第一列开始时,前面必须标上星 号或分号,其他列开始的注释前面必须以分号开头;
85
4.4.1 汇编语言源程序的格式 1. 标号字段(Label Field)
所有汇编指令和大多数汇编伪指令都可以选用标号,供本程序或其它程序调用。 ☆ 标号必须从第一列开始。 ☆ 标号最长32个字符,由英文字母、数字、下划线和美圆符号(A~Z,a~z,0~9,_和$)等组成,但第一个字符不能是数字。 ☆ 标号分大小写。 ☆ 标号后面可以带冒号,但冒号并不处理为标号名的一部分。 ☆ 若不使用标号,则语句的第一列必须是空格、星号或分号。
86
4.4.1 汇编语言源程序的格式 9 000000 1. 标号字段(Label Field) (1)当使用标号时,标号的值是SPC的当前值。
例 使用.word伪指令初始化几个字,其标号 Start将指向第一个字。 该例中标号Start的值为000040H。 … … A Start: .word 0Ah,3,7 ;假设汇编了某个其他代码 标号,值为40h
87
4.4.1 汇编语言源程序的格式 1. 标号字段(Label Field)
(2) 在一行指令中,标号本身是一个有效的语句。标号将SPC的当前值赋给标号,等效于下列伪指令句: label .set $ ;$提供SPC的当前值 (3) 当标号独自占一行时,标号指向下一行指令,而SPC的值不增加。 例如,下列标号Here的值为000043H。 Here: word 3
88
2. 助记符字段Mnemonic Fields 助记符规定了指令所实现的操作功能。它们不能从第一列开始,若从第一列开始,则被认为是标号。
助记符部分可包含下列操作码之一: ① 机器―指令助记符,例如:ADD,MAC,STH,大小写均可; ② 汇编伪指令,例如:.data,.list,.set,以“.”作为前缀,必须小写; ③ 宏伪指令,例如:.macro,.var,.mexit,以“.”作为前缀,必须小写; ④ 宏调用。
89
3. 操作数字段Operand Field 操作数字段给出参与操作的数据来源及存放结果的目标单元。该部分是一个操作数列表,可以是常数、符号或表达式。 LD #lk, 16, dst ☆ 一般位于最左边的是源操作数,中间者(可有可无)是移位的位数,最右边的是目标操作数。 ☆ 汇编器指定常数、符号或表达式用来作为地址、立即数或间接地址。 ☆ 指令操作数可使用前缀# ,
90
4.4.1 汇编语言源程序的格式 4. 注释字段Comment Field
注释可以增强程序的可读性,便于阅读、修改和调试程序。注释中可包含ASCII字符和空格,可使用英文或中文书写。 注意: 若注释从第一列开始,则须以分号或星号开头;若注释从其他任何列开始,则必须用分号而不能使用星号。
91
4.4.2 汇编语言中的常数及字符串 汇编器可支持以下几种类型的常数: 数据类型 举 例 说 明 二进制 1100001b或1100001B
举 例 说 明 二进制 b或 B 八进制 216q或532Q或0216(零开头) 十进制 1234或+1234或-1234 缺省型 十六进制 0B40h或0B40H或0xB40 字符常数 ‘D’ 字符串 “it is a string” 浮点常数 1.523e-23 仅用于C语言 汇编-时间常数 X .set 使用.set伪指令
92
4.4 C54x汇编语言的有关知识 4.4.3 汇编源程序中的符号(Symbols)
汇编源程序中符号可用来作标号Labels、常数constants 和替代字符substitution symbols。 ☆ 由字母、数字以及下划线和美元符号(A~Z,a~z, 0~9,_和$)等组成; ☆ 符号名最多可长达200个字符; ☆ 符号中, 第1位不能是数字, 且符号中不能含空格。
93
4.4 C54x汇编语言的有关知识 4.4.3 汇编源程序中的符号(Symbols)
1. 标号Labels:用作标号的符号和程序的位置有关,在程序中作为符号地址。 2. 符号常数:通过下列两种方法可将常数值赋给符号 ☆ 通过伪指令.set、.equ和.struct/.tag/.endstruct将常数值赋给符号名。 ☆ 使用汇编器的-d选项使常数值与符号相等。 asm500 -d name=[value] 缺省值为1
94
4.4.3 汇编源程序中的符号Symbols 3. 替代符号Substitution Symbols:
将代表一个变量的字符串值赋给符号,这时符号名与该变量等效,成为字符串的别名。 .asg “AR2”, errct;(书错)用errct代替AR2, 引号可省 .asg *+, INC ; 用INC代替*+,省略引号 .asg "*-", DEC; 用DEC代替*- 4. 局部标号Local Labels: 它是一种特殊标号,其使用范围和影响是临时性的。 局部标号可用2种方法定义: ☆ $n,n=0~9。 ☆ name?,这里name是合法符号名。
95
4.4 C54x汇编语言的有关知识 4.4.3 汇编源程序中的符号 4. 局部标号: 局部标号可用下述4种方法之一来取消定义或复位:
☆ 使用.newblock伪指令; ☆ 改变段(利用伪指令.sect,.text或.data); ☆ 通过进入一个include文件(指定.include或.copy伪指令); ☆ 通过离开一个include文件(达到included文件的结尾)。
96
STL A,ADDRC ;存ACC的低16位到ADDRC $1 NOP .newblock
假设符号ADDRA,ADDRB,ADDRC已经在前面作了定义。 Label1: LD ADDRA,A SUB ADDRB,A BC $1,ALT LD ADDRB,A B $2 $ LD ADDRA,A $ ADD ADDRC,A .newblock STL A,ADDRC $ NOP ;将ADDRA装入累加器A ;减去地址B ;如果小于0,分支转移到$1 ;否则将ADDRB装入累加器A ;分支转移到$2 ;$1:将ADDRA装入累加器A ;$2:加上ADDRC ; 取消$1的定义,使它可被再次使用 ;若小于0,分支转移到$1 ;存ACC的低16位到ADDRC .newblock BC $1,ALT ;若小于0,分支转移到$1 STL A,ADDRC ;存ACC的低16位到ADDRC $ NOP .newblock ;错误:$1被多次定义
97
4.4.4 汇编源程序中的表达式Expressions
允许将表达式作为操作数使用。汇编时先计算出表达式的值,然后将该值填入目标代码中。 如 LD #X+((8+5)*2), A 1. 运算符Operators (下页表4.11) ’C54x汇编器使用与C语言相似的优先级。 相同优先级的运算按从左到右的顺序 2. 条件表达式Conditional Expressions 汇编器支持关系操作,可以用于任何表达式。 = 等于 = = 等于 != 不等于 > = 大于或等于 < = 小于或等于 > 大于 < 小于
98
表4.11 指令系统中的运算符及优先级 序号 符 号 运算功能 求值顺序 1 + - ~ ! 取正、取负、按位求补、 逻辑非 从右至左 2
表4.11 指令系统中的运算符及优先级 序号 符 号 运算功能 求值顺序 1 + - ~ ! 取正、取负、按位求补、 逻辑非 从右至左 2 * / % 乘法、除法、求模 从左至右 3 + - 加法、减法 4 ^ 指数 从左到右 5 << >> 左移、右移 从左至右 6 < 小于、小于等于 从左至右 7 > 大于、大于等于 8 != 不等于 从左至右 9 =(=) 等于 从左到右 10 & 按位与运算(AND) 从左至右 11 ∧ 按位异或运算(exclusive OR) 12 | 按位或运算(OR)
99
4.4.4 汇编源程序中的表达式Expressions
3.关于表达式的合法性(Well-Defined Expressions) 某些汇编器要求有效定义的表达式作为操作数。操作数可以是汇编时间常数或链接时可重定位的符号。 所谓合格的表达式是指表达式中的符号或汇编时间常数在被使用之前都已被定义过。 合格表达式的计算必须是绝对的(absolute)。
100
goodsym4 .set label2-label1
3.关于表达式的合法性 例 合格的表达式举例。 .data label1 .word 0 .word 1 .word 2 label2 .word 3 X set 50h goodsym1 .set l00h + X ; 将16位值0,1,2放入标号为 label1的当前段连续字中 ; 将3放入标号为label2的字中 ; 定义X的值 ; 有效定义的表达式 ; $提供SPC的当前值 goodsym2 .set $ goodsym3 .set label1 goodsym4 .set label2-label1 ; 引用已定义的局部标号 ; 有效定义的表达式
101
4.4.4 汇编源程序中的表达式Expressions
3.关于表达式的合法性 所有合法表达式可化简为以下2种形式之一: 绝对符号。绝对符号是指其值不能改变的符号。 可重新定位符号±绝对符号。表达式若不能简化为仅含一个可重新定位符号是非法的,因为这种符号不能被分辨。表达式也不能包含可重新定位符号和外部符号的乘或除。 Expressions that cannot be reduced to contain only one relocatable symbol are illegal.
102
表4.12带有绝对符号和可重新定位符号的表达式的合法性
若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.
103
例4-13 在表达式中绝对符号和可重新定位符号的使用。
例4-13 在表达式中绝对符号和可重新定位符号的使用。 下面的程序中,使用了4个定义在相同段的符号。 .global extern_1 intern_1:.word ‘D’ LAB1: .set 2 intern_2:.word 3 LD #LAB1+((5+4)*3),A LD #LAB1+3+(4*7),A .global extern_1 intern_1:.word ‘D’ LAB1: .set 2 intern_2:.word 3 LD #LAB1+((5+4)*3),A LD #LAB1+3+(4*7),A ; 定义在外部的全局符号 ; 定义在现行模块中,可重新定位 ; LAB1=2,绝对符号 ; 定义在现行模块中,可重新定位 ; LAB1为绝对符号,A=29 ; LAB1为绝对符号,A=33
104
4.4.4 汇编源程序中的表达式Expressions
例4-14 表达式使用例4-13标号的合法性分析 判断下列指令中表达式的合法性。 合法 外部 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 不可将重新定位符号变负 非法 非法 可重新定位符号不可变负 可重新定位符号不可乘除 非法 非法 可重新定位+可重新定位=非法
105
4.4.4 汇编源程序中的表达式Expressions
例4-15 表达式使用例4-13标号的合法性分析 判断下列指令中表达式的合法性。 LD intern_1 - intern_2 + extern_1,B LD intern_1 + intern_2 + extern_1,B LD intern_1 + extern_1 - intern_2,B 合法 可重新定位 绝对符号 可重新定位 =绝对符号 可重新定位 非法 可重新定义+可重新定义=非法 非法 可重新定义+可重新定义=非法 非单操作数运算从左至右 129页,第4行“然后(减)加一个可重新定位符号extern_1”
106
4.5 汇编语言程序设计 4.5.1 DSP基本汇编程序的设计 汇编语言程序具有3种结构形式:
☆顺序结构——指令按顺序被逐条执行,在程序中没有分支和循环,也不调用子程序 。 ☆分支结构——是根据条件是否满足决定程序走向的一种结构 。 ☆循环结构——如果有一段程序需要多次重复执行时,就可以使用循环结构。
107
4.5.1 DSP基本汇编程序的设计 1.顺序结构 初始化程序、算术运算程序、查表程序等采用这种结构。 201字
例4-16 (1) 在RAM空间设置一长度为200字的堆栈段, 段名为”STACK”,堆栈指针SP指向堆栈段高地址stack+200位置。 STACK 解:程序清单: size .set 200 stack .usect ”STACK”, size STM stack+size, SP SP→高地址 低地址 #stack ⁞ 201字 #stack+200 #stack+size RAM (2)计算result=x ×x2, 并将结果存入result单元。
108
4.5.1 DSP基本汇编程序的设计 1.顺序结构 STM #result, AR4 解: .data
例4-16 (2)计算result=x ×x2, 并将结果存入result单元。 STM #result, AR4 SQUR *AR1, B ; B=x12 LD *AR2, T MPY #04h, A ; A=4×x2 ADD A, B STL B, *AR4 .end 解: .data table .word 5, 8, 7 .bss x1,1 .bss x2,1 .bss result,1 .text Start STM #x1, AR1 RPT #2 MVPD table, *AR1+ STM #x1, AR1 STM #x2, AR2 ;B=x12 +4×x2 table AR1→ #x1 #x2 #result 5 8 7 8 5 7 AR2→ 57 AR4→ RAM ROM
109
4.5.1 DSP基本汇编程序的设计 2.分支程序 分支结构又分为单分支和多分支结构。 汇编语言中程序的分支是由条件转移指令实现的。
C54x CPU以累加器A、B及标志位C、TC、OVA、OVB 等的状态作为条件,判断程序是否转移。
110
2.分支程序 方法1:使用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 d1: CMPR 1, AR3 BC d2, TC MVMD AR3, data2 BD loop d2: MVMD AR0, data2 loop: NOP .end 例4-17 编程比较两数data0和data1的大小。若相等,则将其值存入data2单元; 否则将大者存入data2单元。 CMPR CC, ARx If (cond), Then 1→TC Else , →TC 这里多余
111
4.5.1 DSP基本汇编程序的设计 2.分支程序 方法2: 使用SUB 指令
例4-17 编写程序比较两数data0和data1的大小。若相等,则将其值存入data2单元; 否则将大者存入data2单元。 方法2: 使用SUB 指令 方法3: 使用CMPS 指令(顺序结构) data0 .set data1 .set .bss data2, 1 .text LD #data0, 16, a ;将data0送入A(31~16) Add #data1, A ;将data0送入A(15~10) CMPS A, *(data2) ;比较、选择和存储大者 .end data2 直接寻址
112
4.5.1 DSP基本汇编程序的设计 3.循环程序 循环程序通常由下列4部分组成: 置循环初值 循环体(循环处理部分)
循环控制部分,检查循环结束条件是否满足 修改控制变量 有单指令重复RPT[Z] 、块重复指令RPTB,和BANZ指令。 用BANZ一条指令可同时完成循环计数器的修改和循环的跳转。 STM #99,AR1; Loop: RPT #999 ; NOP ; BANZ loop, *AR1- ; 例4-18 多重循环延时。
113
3.循环程序 例4-18 采用多重循环的延时程序。 设机器周期为20ns,则下列程序的延时时间为: ns×[2+( )× ]= ns≈2ms STM #99, AR1 ;2个机器周期, 外循环100次 Loop: RPT # ;1个机器周期 NOP ;1个机器周期, 内循环1000次 BANZD Loop, *AR1- ;4个机器周期(条件真) ;2个机器周期(条件假) NOP Loop:
114
4.5 汇编语言程序设计 4.5.2 DSP的模块化程序设计及汇编连接过程
在编写C54x汇编程序时,可将程序分为多个模块(或文件),每一程序模块都有明确的任务和功能。如主程序、中断处理程序、子函数、共享文件、命令文件等。 根据每个模块的不同功能,选择结构、伪指令 和指令进行编程,然后将多个文件组合在CCS环境 的同一工程(project)中,通过汇编连接,最终形成 一个可执行文件。
115
BD _c_int00;复位时跳入主程序入口 _c_int00
1.编写中断处理程序vectors.asm 通过中断处理程序开辟出中断矢量表的存储空间,进行中断入口地址的跳转处理。特别是复位入口地址,起到上电引导作用。 例4-20 如果只进行软件仿真调试,而没有硬件中断产生,则可以采用下列简单的复位中断处理程序vectors.asm。 .ref _c_int00 ;主程序入口 _c_int00 .sect "vectors" int_RESET: BD _c_int00;复位时跳入主程序入口 _c_int00 NOP .space 124*16 ;没有使用其它中断, 保留空间 .end
116
BD _c_int00; 复位时跳入主程序入口 _c_int00
1.编写中断处理程序vectors.asm 例4-19: 有定时硬件中断时,为防中断跑飞 .ref _timer_isr 通过中断处理程序开辟出中断矢量表的存储空间,进行中断入口地址的跳转处理。特别是复位入口地址,起到上电引导作用。 ..... NMI: RETE ;非屏蔽中断,开中断返回 NOP ; sint17 .space 4*16 ; 保留空间 TINT0: BD _timer_isr ; 转定时中断服务 PSHM ST0; PSHM ST1; DMAC5: RETE; DMAC5中断,开中断返回 .end 例4-20 如果只进行软件仿真调试,而没有硬件中断产 生,则可以采用下列简单的复位中断处理程序。 .ref _c_int00 ;主程序入口 _c_int00 .sect "vectors" int_RESET: BD _c_int00; 复位时跳入主程序入口 _c_int00 NOP .space 124*16 ; 没有使用其它中断, 保留空间 .end
117
4.5.2 DSP的模块化程序设计及汇编连接过程 2.编写主程序和头文件 应尽量使主程序结构简洁,以函数调用为主,突 出主程序的主体轮廓。
对重复出现的算法或较复杂的程序部分,可将其 编写成子程序或宏。 可将一些全局标号、常量、变量、寄存器名、位 名等存放在一个或几个头文件中,做为共享文件 来使用。
118
STM #x, AR4; 无vectors.asm,时流水线冲突 ,前需插多个nop 指令
例4-21写出计算 的主程序test.asm。 解: .bss a, 6 .bss x, 6 .bss y, 1 .data Table: .word 1,2,3,4,5,6 .word 0Ch, 0Ah,8,6,4,2 .text STM #a, AR1 RPT #0Bh MVPD Table, *AR1+ STM #a, AR3 STM #x, AR4; 无vectors.asm,时流水线冲突 ,前需插多个nop 指令 RPTZ A, #5 ;累加器A清0,下条指令重复执行6次 MAC *AR3+, *AR4+, A ; STL A, *AR4; loop: B loop .end 2.编写主程序和头文件 (Xmem)×(Ymem)+(src)→dst (Xmem) → T ;STM #y, AR7 (书上AR7)
119
3.编写命令文件 test.cmd 参考4.2.3节。 命令文件负责为连接器提供段定位信息。 例4-22 命令文件test.cmd vectors.obj test.obj -o test.out -m test.map MEMORY { PAGE 0: EPROM: org=0xE000, len=0x100 VECS: org=0xFF80, len=0x80 PAGE 1: DARAM: org=0x0080, len=0x20 SPRAM: org=0x0100, len=0x0020 } SECTIONS { .text:> EPROM PAGE 0 .data:> EPROM PAGE 0 .bss:> SPRAM PAGE 1 .STACK:> DARAM PAGE 1 .vectors:> VECS PAGE 0 }
120
参考:TMS320C54x Code Composer Studio Tutorial.pdf,spru327c,2000,TI官网
4.5.2 DSP的模块化程序设计及汇编连接过程 4.编辑、编译、汇编和连接生成各种文件 1)编辑:用户可在任何文本编辑环境下编写C源文件.c或汇编源文件.asm。 2)编译:若采用C语言,则需要调用C编译器将.c文件编译成汇编语言文件.asm。 3)汇编:用汇编语言编写的源程序或者来自C编译器编译的汇编源程序被送入汇编器进行汇编。 参考:TMS320C54x Code Composer Studio Tutorial.pdf,spru327c,2000,TI官网
121
4.5.2 DSP的模块化程序设计及汇编连接过程 3)汇编 汇编器主要完成下列工作:
将汇编语言源文件汇编产生一个可重新定位的目标文件(后缀.obj)。 根据需要,产生源程序列表文件(后缀.lst),并对源程序列表文件进行控制。 将代码分为若干段,为每个目标代码段都设置一个段程序计数器SPC。 定义和引用全局符号。 汇编条件块。 支持宏定义和宏调用。
122
4.5.2 DSP的模块化程序设计及汇编连接过程 ASM500命令格式如下:
asm500 [input file [object file [listing file]]] [-options] input file: 汇编源文件名,缺省后缀为.asm object file: 编译输出的OBJ文件名,缺省后缀为.obj listing file: 产生的列表文件名,缺省后缀为.lst options: 编译器使用的各种选择。选项举例: -c: 若使用该选项,编译器忽略字母的大小写。例如abc与ABC是一样的。系统缺省为区分大小写。
123
3)汇编 表4.12 C54x汇编器的选项及功能 选项 功 能 -@
功 能 避开命令行长度的限制。在一个命令文件中,文件名或选项参数中包含了嵌入的空格或连字号,则必须使用引号括起来,例如:“this-file.asm” -a 建立绝对列表文件。选用-a时,汇编器不产生目标文件 -c 使汇编语言文件中大小写没有区别 -d 为名字符号设置初值。格式为-d name[=value]时,与汇编文件被插入 name .set [=value]是等效的。 -f 抑制汇编器给没有.asm扩展名的文件添加扩展名的默认行为 -g 允许汇编器在源代码中进行代码调试。汇编语言源文件中每行的信息输出到COFF文件中。 -h, -help, -? 这些选项任一个将显示可供使用的汇编器选项的清单 -hc 将选定的文件复制到汇编模块。 -hi 将选定的文件包含到汇编模块。
124
3)汇编 续表4.12 选项 功 能 -i 规定一个目录,汇编器可以在这个目录下找到.copy、.include或.mlib命令所命名的文件 。 -l (英文小写l)生成一个列表文件 -mf 指定汇编调用扩展寻址方式 -mg 源文件是代数式指令 -q 抑制汇编的标题以及所有的进展信息 -r, -r[num] 压缩汇编器由num标识的标志。 -pw 对某些汇编代码的流水线冲突发出警告 -u -u name取消预先定义的常数名,不考虑-d选项所指定的常数 -v -v value确定使用的处理器,可用541,542,543,545,5451p,5461p,548,549值中的一个 -s 把所有定义的符号放进目标文件的符号表中。 -x 产生一个交叉引用表。
125
4.5.2 DSP的模块化程序设计及汇编连接过程 4)连接 连接器将目标文件合成为可执行的.out文件。 它主要完成下列任务:
按照目标系统的实际硬件将段配置到存储器空间; 对符号和段进行重新定位,并确定最后的地址; 确定输入文件之间未定义的外部引用。 连接器的命令行格式如下: lnk500 [-options] filename1 … filenamen 例 lnk500 [-o test.out] test1.obj test2.obj [-m test.map]
126
4)连接 表 4-13 C54x连接器的常用选项及功能 选 项 功 能 -a 生成一个绝对地址的、可执行的输出模块。 -ar0
生成一个可重新定位、可执行的目标模块。 -e global_symbol 定义一个全局符号,所对应的程序存储器地址,称为入口地址。 -f fill_value 对输出模块各段之间的空单元设置一个16位数值(fill_value)。 -i dir 更改搜索文档库算法,先到dir(目录)中搜索。 -l filename 命名一个文档库文件作为链接器的输入文件 。 -m filename 生成一个.map映像文件,filename是其文件名。 -o filename 对可执行输出模块命名。如果默认,则此文件名为a.out -r 生成一个可重新定位的输出模块。
127
4.5.2 DSP的模块化程序设计及汇编连接过程 5)调试
.out文件提供的指令代码可送入CCS调试环境进行调试,以验证程序的正确性。若需要,用Hex代码转换程序将 .out文件转换成.hex文件,用编程器将程序写入 EPROM/FLASH中,形成DSP独立系统。 编程者还可通过选项获得下列的两个文件,它们在调试的过程中会对编程者有所帮助 : 通过汇编器的选项-l产生一个后缀为.lst的列表文 件。(如例4-2 ) 通过连接器的选项-m产生一个后缀为.map的映 射文件。(如例4-23)
128
4.5.2 DSP的模块化程序设计及汇编连接过程 5)调试 .out文件提供的指令代码可送入CCS调试环境进行调试,以验证程序的正确性。
例4-23 test.map 5)调试 例4-23 参考映象文件demo.map .out文件提供的指令代码可送入CCS调试环境进行调试,以验证程序的正确性。 主程序入口 _c_int00 编程者还可通过选项获得下列的两个文件,它们在调试的过程中会对编程者有所帮助 : 通过汇编器的选项-l产生一个后缀为.lst的列表文件。(如例4-29) 通过连接器的选项-m产生一个后缀为.map的映射文件。(如例4-30)
129
.out文件提供的指令代码可送入CCS调试环境进行调试,以验证程序的正确性。
第4章 汇编语言程序设计 5)调试 .out文件提供的指令代码可送入CCS调试环境进行调试,以验证程序的正确性。 编程者还可通过选项获得下列的两个文件,它们在调试的过程中会对编程者有所帮助 : 通过汇编器的选项-l产生一个后缀为.lst的列表文件。(如例4-29) 通过连接器的选项-m产生一个后缀为.map的映射文件。(如例4-30)
130
4.5 汇编语言程序设计 4.5.3 DSP定点算法设计 1. 定点数的定标 计算机有两种数据表示方法: 定点数表示法 浮点数表示法
定点数就是小数点位置固定的数。数据的表示形式是: 符号位 整数部分.小数部分 C54x是定点芯片,采用补码形式来表示无符号数和有符号数。
131
4.5 汇编语言程序设计 4.5.3 DSP定点算法设计 2. Q表示法
CPU在执行指令时,并不知道处理的数据是整数还是小数,也不能指出小数点的位置。在编程时必须由程序员指出一个数的小数点处于哪一位,这就是定标的概念。 常用的定标方法是Q表示法,Q表示法用Q0,Q1,… Qi, …, Q15 分别表示小数点在D0位之后、D1位之后、…Di位之后、…D15位之后。
132
表4.14 Q表示法 Q表示 小数点位置 整数位 小数位 精度--幂 Q15 在D15之后 15 -1~0.9999695 2 -15
十进制表示范围 精度--幂 Q15 在D15之后 15 -1~ 2 -15 Q14 在D14之后 1 14 -2~ 2 -14 Q13 在D13之后 2 13 -4~ 2 -13 Q12 在D12之后 3 12 -8~ 2 -12 Q11 在D11之后 4 11 -16~ 2 -11 Q10 在D10之后 5 10 -32~ 2 -10 Q9 在D9之后 6 9 -64~ 2 -9 Q8 在D8之后 7 8 -128~ 2 -8 Q7 在D7之后 -256~ 2 -7 Q6 在D6之后 -512~ 2 -6 Q5 在D5之后 -1024~ 2 -5 Q4 在D4之后 -2048~ 2 -4 Q3 在D3之后 -4096~ 2 -3 Q2 在D2之后 -8192~ 2 -2 Q1 在D1之后 14 1 -16384~ 2 -1 Q0 在D0之后 15 -32768~36767 2 0
133
- 𝟏 𝟐 𝟏𝟓 (FFFFh) 4.5 汇编语言程序设计 4.5.3 DSP定点算法设计 2. Q表示法
例4-24 Q15将小数点设置在D15之后。 可表示的数值范围: -1~ (8000h~ 7FFFh) 最小负数: -𝟏 (8000h) 最大负数: - 𝟏 𝟐 𝟏𝟓 (FFFFh) 最大正数: 𝟐 −𝟏 + 𝟐 −𝟐 +…+𝟐 −𝟏𝟓 = (7FFFh) 精度: 𝟐 −𝟏𝟓
134
4.5 汇编语言程序设计 4.5.3 DSP定点算法设计 3. Q值的确定
在使用定点定标时,如何选择合适的Q值是一个关键性问题。在实际的DSP工程环境中,参与运算的变量都有一定的动态范围,只要这个动态范围确定了,Q值也就确定了。 为了防止异常或溢出,应该将Q值取低,即将数据格式放大。 Q15 Q14 ……Q0格式 高 …… 低
135
4.5.3 DSP定点算法设计 4.定点算术运算 以下主要介绍: 定点加法运算 定点乘法运算 1)定点加法运算 两定点数相加注意下列两点:
在数字信号处理算法中,大量运算是乘法和累加。一般情况下,应尽量采用纯整数运算或纯小数运算,即全部数据用Q0格式表示,或用Q15格式表示。 以下主要介绍: 定点加法运算 定点乘法运算 1)定点加法运算 两定点数相加注意下列两点: 被加数和加数必须有相同的Q值; 结果是否会溢出。
136
1)定点加法运算 例4-28 计算 =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 0.5∗𝟐 𝟏𝟒 ;x 直接寻址 ;x+1直接寻址
137
2)定点乘法运算 因为16位×16位=32位,所以乘法不会产生溢出。 两定点数相乘通常有下列三种情况:
整数×整数:Q0×Q0=Q0,结果仍为纯整数,小数 点在结果的D0位后面。 小数×小数:Q15×Q15=Q30,结果仍为纯小数,小数 点在乘积D30位后面,也就是说,D31和D30位都是符 号位,且其值相同。 可左移1位,去掉多余符号,然后保留高16位,仍为 Q15定标。FRCT置1即自动完成。 混合小数乘法:Qi×Qj = Qi+j
138
2)定点乘法运算 例4-29 纯小数乘法:计算0.35×0.9 = 0.315。 .bss x,2 .bss prod,1 ;只保留高16位 table: .word 35*32768/100 ;Q15定标 .word 9*32768/10 ;Q15定标 .text 𝐒𝐒𝐁𝐗 𝐅𝐑𝐂𝐓; 乘积小数点左移一位 STM #x,AR2 RPT #1 MVPD table,*AR2+ STM #x,AR4 STM #x+1,AR5 MPY *AR4,*AR5,A 𝐒𝐓𝐇 A,*(prod);小数点左移一位, 乘积A为Q31定标, ;乘积32位,只保留高16位的乘积。 程序: 285h 0.35∗𝟐 𝟏𝟓 2CCCh 0.𝟗∗𝟐 𝟏𝟓 7333h
139
2)定点乘法运算 例4-30 混合小数乘法:计算7.62×1.84 = 。 程序段如下: .bss x,2 .bss prod,2 ; 保留乘积32位 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位的处理。 7.62∗𝟐 𝟏𝟐 1.84∗𝟐 𝟏𝟒
140
4.5 汇编语言程序设计 4.5.4 非线性运算及数据的非数值处理
非线性运算及数据的非数值处理 在DSP的数值运算中,除基本的加减乘除运算外,还有其他许多非线性运算,如对数运算、开方运算、指数运算、三角函数运算等,实现这些非线性运算的方法一般有: (1)调用厂家(TI)提供DSP编译系统的库函数; (2)查表法; (3)级数展开法、插值法、迭代法。
141
1. 调用厂家(TI)提供DSP编译系统的库函数
非线性运算及数据的非数值处理 1. 调用厂家(TI)提供DSP编译系统的库函数 TMS320C2X/C5X 的C编译器提供了比较丰富的运行支持库函数。在这些库函数中,包含了诸如对数、开方、三角函数、指数等常用的非线性函数。 在C程序中(也可在汇编程序中)只要采用与库函数相同的变量定义,就可以直接调用。 运算量大,耗费时间长。
142
2 查表法 表分一维表, 二维表, 三维表等; 常用线性表, y=f(x) 。
2 查表法 表分一维表, 二维表, 三维表等; 常用线性表, y=f(x) 。 采用这种方法必须根据自变量的范围和精度要求制作一张表格。显然输入的范围越大,精度要求越高,则所需的表格就越大,即存储量也越大。 查表法求值所需的计算就是根据输入值x确定表的地址, 根据地址就可得到相应的值y=f(x), 因而运算量较小。 查表指令:MVPD, READA( 累加器的低8位可包含被查表的程序存储器地址,可通过计算指定表的位置。) 部分型号片内ROM 的地址FC00h~FEFFh (2.4.1节)固化了μ律扩展表, A律扩展表, sin函数表。
143
非线性运算及数据的非数值处理 3.级数展开法、插值法、迭代法 (1) 提高查表法的精度 (2) 扩大自变量范围
144
4.5 汇编语言程序设计 4.5.5 流水线冲突及其解决的方法
流水线冲突及其解决的方法 采用C/C++语言编程,经过C编译器产生的代码避免了资源争用和时序上的错误,不会产生流水线冲突。 采用汇编语言编程,在下列情况下可能会产生流水线冲突: 对MMR进行写操作所引发的流水线冲突 条件执行指令有可能发生的流水线冲突 改变PMST可能引起的流水线冲突
145
1.对MMR进行写操作所引发的流水线冲突 对下列硬件资源进行写访问时有可能产生未保护性的流水线冲突(IMR,IFR,TRN,REA,RSA,XPC除外): 累加器AG、AH、AL、BG、BH、BL 状态寄存器ST0、ST1 处理器工作方式状态寄存器PMST 辅助寄存器AR0~AR7 堆栈指针SP 暂存器T 块重复计数器BRC 重复块长度寄存器BK
146
1.对MMR进行写操作所引发的流水线冲突 例4-33 分析下列指令的流水线冲突及解决方法。 STLM A, AR1;(A)→AR1
STM #8, AR2;8→AR2 它们的流水线操作如下图所示。两条指令在写MMR时产生了资源争用,也就产生了流水线冲突。 时序性流水线冲突
147
1.对MMR进行写操作所引发的流水线冲突 解决方法是:在两条指令之间插入1个空操作NOP,
则流水线变为下图所示。写AR2的时间延时了一个周期,避开了写操作的资源争用,解决了流水线的冲突。
148
例4-34 分析下列指令的流水线冲突及解决方法。 STLM A, AR3 LD *AR3, B
1.对MMR进行写操作所引发的流水线冲突 例4-34 分析下列指令的流水线冲突及解决方法。 STLM A, AR3 LD *AR3, B 数据未准备好冲突,产生逻辑错误 本应该是先写入 AR 3 , 再读 地址 中的值送给 B ; 结果却并非如此。 !
149
1.对MMR进行写操作所引发的流水线冲突 例4-34 STLM A, AR3 LD *AR3, B
STM为双字指令,占两条流水线,一旦常数译码后,马上写至AR3 解决之道1:STM #lk, AR LD *AR3, B
150
1.对MMR进行写操作所引发的流水线冲突 例4-34 解决之道2:插入空指令 STLM A, AR3 插入多少NOP? NOP
LD *AR3, B 插入多少NOP? 访问MMR操作表4-18!
151
4.5.5 流水线冲突及其解决的方法 2.条件执行指令有可能发生的流水线冲突 例4-35 分析下列程序的流水线操作情况,其流水线如下图所示。
流水线冲突及其解决的方法 2.条件执行指令有可能发生的流水线冲突 例4-35 分析下列程序的流水线操作情况,其流水线如下图所示。 LD *AR2, B XC 2, BEQ ;若(B)=0,则执行后面的2条指令 …… 逻辑性流水线冲突
152
4.5.5 流水线冲突及其解决的方法 2.条件执行指令有可能发生的流水线冲突
流水线冲突及其解决的方法 2.条件执行指令有可能发生的流水线冲突 解决的方法是:在两条指令中插入2个NOP,使得条件稳定后再去进行条件检测。
153
3.改变PMST可能引起的流水线冲突 在处理器工作方式状态寄存器(PMST)中有一些非常重要的位,在修改PMST的这些位时,如果紧跟其后的指令立即使用新的地址空间去进行访问,就有可能产生错误。 OVLY, DROM MP/MC, IPTR, 例4-36 在修改DROM位之后,插入3个NOP,才能去访问它所影响的存储空间。 ORM #8h, PMST ;令DROM =1,本例设DP=0 NOP LD *AR3, A ;从片内ROM读数据
154
4.5.5 流水线冲突及其解决的方法 3.改变PMST可能引起的流水线冲突
流水线冲突及其解决的方法 3.改变PMST可能引起的流水线冲突 例4-37 在修改MP/MC位之后,插入2个NOP,才能对它所配置的存储空间进行操作。 STLM A, PMST ;假设该指令使MP/MC=1 NOP CALLD offchip ;调用片外程存子程序offchip STM #k, AR1
155
解决流水线冲突方法(表4-18访问MMR的建议)
通过前面分析看出,解决流水线冲突的方法主要是: 1)插入NOP指令,延长流水线的执行时间。 2)选用合适的指令,避免产生逻辑性错误。 例4-38 分析程序段的流水线操作。 RSBX SXM ;SXM清零 ;或者 SSBX SXM ADD *AR1(10h),A ;((AR1+10h))+(A)→A,双字双周期指令 ADD *AR1,A ;书中指令前应插入NOP指令 在RSBX SXM指令的后面本应该插入一个NOP,但由于ADD *AR1(10h),A 指令为双字指令,隐含了一个保护周期,因此,两条指令之间不需要再插入NOP。
156
作业 习题4.2,4.4, 4.5,4.8, 4.11, 4.18,4.19
Similar presentations