《STM8S系列单片机原理与应用》课件第4章_第1页
《STM8S系列单片机原理与应用》课件第4章_第2页
《STM8S系列单片机原理与应用》课件第4章_第3页
《STM8S系列单片机原理与应用》课件第4章_第4页
《STM8S系列单片机原理与应用》课件第4章_第5页
已阅读5页,还剩204页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第4章STM8指令系统

4.1ST汇编语言格式及其伪指令

4.2STM8S寻址方式4.3STM8S指令系统4.1ST汇编语言格式及其伪指令

4.1.1ST汇编常数表示法在缺省情况下,ST汇编语言数制表示方式与Motorola汇编语言格式相同,与Intel汇编语言表示方式不同。其中,二进制、十六进制、十进制数表示方式如下:

%10100101 — 二进制数表示方式(用“%”作前缀,指示随后的数为二进制数)。

$5A — 十六进制数表示方式(用“$”作前缀,指示随后的数为十六进制数)。

12 — 十进制数表示方式(没有前、后缀指示符)。* — 表示程序计数器PC的当前值。不过,如果程序员习惯了Intel汇编语言数制表示方式,则可在程序中使用Intel伪指令,指示程序中随后的数据格式采用Intel汇编语言格式表示。例如:

Intel ;指示随后的指令系列采用Intel格式数制即

10100101B — 二进制数表示方式(用“B”作后缀,指示该数为二进制数)。

5AH — 十六进制数表示方式(用“H”作后缀,指示该数为十六进制数)。

12 — 十进制数表示方式(没有前、后缀指示符)。

$ — 表示程序计数器PC的当前值。4.1.2ST汇编语言格式

ST汇编语言格式与Intel汇编语言格式基本相同,如下所示。

[标号[:]]操作码助记符[第一操作数],[第二操作数],[第三操作数] [;注释]举例:

Next:ADDA,$10 ;累加器A与10H单元内容相加,结果保存到A中

BTJT$1000,#2,LOOP1 ;若1000H单元的b2位为1,则跳转到LOOP1标号处执行操作码助记符是指令功能的英文缩写,必不可少。例如,用“ADD”作为加法指令的操作码助记符;用“BTJT”作为“位测试为真”转移指令的操作码助记符,“BTJT”就是“BitTestandJumpifTrue”的英文缩写。指令操作码助记符后是操作数,不同指令所包含的操作数个数不同:有些指令,如空操作指令“NOP”就没有操作数;有些指令仅含有一个操作数,操作数与操作码之间用“空格”隔开,如累加器A内容加1指令,表示为“INCA”,其中INC为指令操作码助记符,是英文“Increase”的缩写,A是操作数;有些指令含有两个操作数,例如,将立即数55H传送到累加器A中的指令表示为“LDA,#$50”,其中LD是指令操作码助记符,第一操作数为累加器A,第二操作数为“$50”,#表示立即数;有些指令含有三个操作数,如“当某存储单元指定位为1时转移”指令,用“BTJT$1000,#2,LOOP1”表示,其中BTJT是指令操作码助记符,LOOP1是标号,即相对地址。在多操作数指令中,各操作数之间用“,”(逗号)隔开。在双操作数指令中,第一操作数有时称为目的操作数,第二操作数有时称为源操作数。“;”(分号)后的内容是注释信息。在指令后加注释信息是为了提高程序的可读性,以方便阅读、理解该指令或其以下程序段的功能。汇编时,汇编程序不理会分号后的注释内容,换句话说,加注释信息不影响程序的汇编和执行,因此,注释信息可以加在指令行后,也可以单独占据一行。标号是符号化了的地址码,在分支程序中经常用到。标号由英文字母(大写、小写)、数字(0~9)及“_”(下划线)构成,最长为30个字符。注意:“数字”不能作为标号的第一个字符。例如,“task1_next1”是合法标号;而“8ye_next1”不是合法标号,原因是首字符为数字8。另外,在ST汇编中,要严格区分标号的大小写。在ST汇编中,位于00段内的地址标号后可带“ : ”(冒号),也可以不带冒号,且标号一律顶格书写。标号分为三大类:公共标号(Public),由本模块定义,在整个项目内有效,项目内另一个模块引用时须用Extern伪指令申明;局部标号,仅在本模块内有效;外部标号(Extern),由另一个模块定义且声明为公共标号。此外,标号还具有长度属性—字节,00页内的标号,带后缀 .B;字标号,00段内的标号,带后缀 .W;长标号,存放位置没有限制,带后缀.L。不带后缀长度属性说明符的标号默认为字标号,即 .W类型。4.1.3ST汇编支持的关系运算符

ST汇编指令中的常数可以是二进制、十六进制、十进制常数,也可以是表4-1所示的运算符及其组合。表4-1关 系 运 算 符在表4-1中:

(1) a、b均为非负整数。

(2)当指令中的常数为关系运算式的结果时,必须用“{}”(花括号)将关系运算符括起来。例如:

LDA,#{HIGH1234H} ;该指令的含义将1234H常数的高8位12H送A

LDWX,#{45MULT36} ;将45 × 36送索引寄存器X

(3)由于STM8S汇编指令中没有位赋值指令,因此“布尔运算符”仅出现在条件汇编伪指令中。4.1.4ST汇编伪指令(Pseudoinstruction)在汇编语言源程序中,除了包含可以转化为特定计算机系统的机器语言指令所对应的汇编语言指令外,还可能包含一些伪指令,如“#define”、“EQU”、“END”等。“伪”者,假也,尽管它不是计算机系统对应的指令,汇编时也不产生机器码,但汇编语言源程序中的伪指令并非可有可无。伪指令的作用是:指导汇编程序(或编译器)对源程序进行汇编。伪指令不是CPU指令,汇编时不产生机器码。显然,伪指令与CPU类型无关,而与汇编程序(也称为汇编器或编译器)的版本有关。在汇编语言源程序中引用某一条伪指令时,只需考虑用于将“汇编语言源程序”转化为对应CPU机器语言指令的“汇编程序”是否支持所用的伪指令。

1)符号常数定义伪指令 #define符号常数、寄存器、寄存器中指定位以及I/O引脚重命名等,均可用 #define伪指令定义为某一字符串形式。ST8汇编最多支持4096条 #define指令,格式如下:

#define常量名值 ;位于程序头内例如:#defineVAR1$30 ;常量VAR1为30H如果在程序头中使用下列Define伪指令:#DefineTELE_DDRPD_DDR,#3 ;“PD_DDR,#3”被定义为TELE_DDR字符串#DefineTELE_CR1PD_CR1,#3 ;“PD_CR1,#3”被定义为TELE_CR1字符串#DefineTELE_CR2PD_CR2,#3 ;“PD_CR2,#3”被定义为TELE_CR2字符串#DefineTELE_InPD_IDR,#3 ;“PD_IDR,#3”被定义为TELE_In字符串对PD3引脚控制寄存器、数据输入寄存器进行重命名后,就可以在程序中直接引用,如下所示:

BRESTELE_DDR ;与“BRES

PD_DDR,#3”指令等效

BSETTELE_CR1 ;与“BSETPD_CR1,#3”指令等效

BRESTELE_CR2 ;与“BRESPD_CR2,#3”指令等效

BTJTTELE_In,NEXT1 ;与“BTJTPD_IDR,#3,NEXT1”指令等效这种做法的好处非常明显,由于某种原因TELE_In信号不从PD3引脚输入,而是从其他引脚输入,则仅需更换程序头中Define指令所指的寄存器名与引脚编号即可。不过,很少需要在程序中更改引脚输入/输出属性的情况,因此也可以不重定义Px_DDR、Px_CR1、Px_CR2寄存器位,而仅定义数据输出寄存器Px_ODR位(输出引脚)、数据输入寄存器Px_IDR位(输入引脚),如下所示:;输出引脚

BSETPD_DDR,#2 ; 1(输出),输出允许OE/CE,在PD口的b2位

BSETPD_CR1,#2 ; 1,互补推挽方式

BRESPD_CR2,#2 ; 0,选择低速方式

#defineOE_HT9170PD_ODR,#2 ;将PD_ODR,#2定义为“OE_HT9170”

BSETOE_HT9170 ; 1,开始时OE置为1(允许HT9170解码输出);输入引脚

BRESPD_DDR,#7 ; 0(输入),解码有效DV,在PD口的b7位

BSETPD_CR1,#7 ; 1,带上拉输入方式

BSETPD_CR2,#7 ; 1(允许中断)#DefineDV_HT9170PD_IDR,#7 ;将“PD_IDR,#7”引脚定义为“DV_HT9170”可以用#define指令定义外设控制寄存器、状态寄存器中的位,提高源程序的可读性。例如:#defineRST_SR_IWDGF RST_SR,#1;将“RST_SR,#1”用“RST_SR_IWDGF”字符串取代#defineRST_SR_ILLOPF RST_SR,#2;将“RST_SR,#2”用“RST_SR_ILLOPF”字符串取代由#define定义的符号常量不支持重定义功能,既不能用另一条 #define指令再定义同一字符常量,也不能用EQU伪指令再赋值。

2) EQU与CEQU伪指令用EQU(不支持重定义)以及CEQU(可重定义)伪指令可以定义标号常量与变量,按标号定义与书写。在ST8汇编中,将EQU、CEQU定义的常量、变量视为标号。例如:

var2EQU$30 ;把var2定义为30H,var2,既可以视为常量,也可以视为变量。作变量时,是

; RAM还是ROM存储单元,与EQU后指定的数值有关

LDA,#var2 ;立即数寻址,作常量

LDA,var2 ;直接寻址,即存储单元地址,视为变量。该指令与“LDA,$30”指令等效

CEQU伪指令用法与EQU相似,唯一区别是用CEQU定义的标号常数、变量允许用另一条“CEQU”伪指令重新定义。由EQU、CEQU伪指令定义的标号常量、变量可以放在RAM、ROM、EEPROM段中,不过最好放在程序头部分。

3)标号属性说明伪指令PUBLIC与EXTERN无论是常量、变量定义标号,还是程序中转移目标地址标号,均存在三个属性:标号长度(字节标号、字标号、长标号)、作用范围(局部标号、全局标号以及外部标号)、关联性(绝对标号与相对标号)。标号长度属性可用“.B”(字节标号)、“.W”(字标号)、“.L”(长标号,三个字节)后缀符逐一指定,如下所示:

Labe_2.b EQU $30 ;字节标号

Labe_1.w EQU $30 ;等同于“Labe_1

EQU$30”,字标号

Labe_2.L EQU $1230 ;长标号(三字节)也可以用“Bytes”、“Words”或“Longs”伪指令指定多个同一种长度类型标号,如下所示:

Bytes

R00DS.B1

R01DS.B1

R02DS.B1

Words

R10DS.B1

R11DS.B1

R12DS.B1凡是没有特别说明的标号,均属于局部标号,只在本模块内有效。对于全局标号,须用“PUBLIC”伪指令说明或“.label”(带前缀.)声明。例如:

PUBLICtask_1 ;用BUPLIC伪指令声明

.task_1 ;直接用前缀点“ . ”定义全局标号task_1(推荐使用这种方式)

.task_2 ;直接用前缀点“ . ”定义全局标号task_2本模块调用另一个模块定义的全局标号,应在模块头用“EXTERN”伪指令说明该标号来自另一个模块。例如:

EXTERNtask_1,task_2 ;说明这两个标号来自另一个模块绝对标号常用于定义常量,程序没有汇编时,标号的值是确定的,如用EQU或 #define指令定义的常量标号。相对标号包括转移指令中的标号、在RAM或EEPROM存储区内用DS(DS.B、DS.W、DS.L)伪指令定义的变量,相对标号的值,即对应的存储单元地址,必须经过编译、连接后才能确定。

4)标号长度定义伪指令位于特定段内的标号地址长度可以是Byte、Word、Long,缺省时标号地址长度为Word,可以重新指定标号的地址长度。例如,在起始地址为0100的RAM段中,标号地址长度为16位,可以用Long指定为24位(3字节)。例如:

segment'ram1'

Variable.L ;标号Variable的长度定义为long(后缀 .L) dc.b$50不能在起始地址为0100H的段内将标号定义为Byte,原因是其物理地址至少为16位;同理,不能将位于10000H单元后的标号定义为 .W类型,原因是其物理地址为24位,只能定义为 .L类型。

3.段定义伪指令Segment段是一个非常重要的概念,段与存储区关联,定义如下:

[<name>]segment[<align>][<combine>]'class'[cod]其中:

(1) name为段名(最长为12个字符),可选。

(2) align为定位类型:可以是Byte(字节,其始于任意一个地址)、Word(字,起始于0、2、4等偶数地址)、Long(4个字节,起始于0、4、8、C)等。

(3) combine为组合类型:可以为at:x[-y](段的起始地址与终了地址)、command(公共段)。

(4) class为段的别名。引号内为别名,最长为30个字节,不能省略。例如:

BYTES ; 8位地址形式标号

segmentbyteat00-FF'ram0' ;起始地址、终了地址均默认为十六进制,无须加“H”或“$” WORDS ; 16位地址形式标号

segmentbyteat1000-13FF'ram1' WORDS ; 16位地址形式标号

segmentbyteat1400-17FF'stack' WORDS ; 16位地址形式标号

segmentbyteat4000-47FF'eeprom' WORDS ; 16位地址形式标号

segmentbyteat8080-27FFF'rom' WORDS ; 16位地址形式标号

segmentbyteat8000-807F'vectit'在ST汇编中,一个模块内最多可定义128个段,但至少需要定义一个代码段。采用下列的段定义,强迫其后定义的变量从字边界开始存放。

segmentLong'eeprom' ;定位类型为Long,即从4字节边界开始。该段起始地址由前面

;别名相同的段指定Var2ds.b2 ; Var2的地址末位为0、4、8等

4.中断服务程序定义伪指令interrupt中断服务程序定义伪指令结构如下:

Interrupt中断入口标号中断入口标号.L

IRET ;中断返回指令然后,把中断服务程序地址标号填入中断入口地址表中。

5.常用条件汇编伪指令

ST汇编支持条件汇编伪指令,常用条件汇编伪指令的结构如下:

(1)第一种:

#IF{表达式} ;表达式为真,则汇编随后的指令系列

#ELSE ; ELSE可选

#ENDIF

(2)第二种:

#IFdef<变量、标号或字符串> ;含义是指定的变量、标号或字符串存在,则

;汇编随后的指令(不支持运算符)

#ELSE ; ELSE可选

#ENDIF

6.其他

1) DC伪指令在ST汇编中,DC伪指令用于在ROM段中定义字节、字、双字常数表,包括了:

DC.Bn1,n2,n3,…

;字节常数(8位整数)定义伪指令,将随后的一串8位二进制数

; (字节,彼此间用逗号隔开)连续存放在ROM存储区中用于定义;字节常数表

DC.Wnn1,nn2,nn3…

;字常数(16位整数)定义伪指令,将随后的一串16位二进制数

; (两个字节,彼此间用逗号隔开)连续存放在ROM存储区中用于;定义字常数表在STM8系列CPU中,字、双字(由四个字节组成)等的存放规则是:低字节存放在高地址中,高字节存放在低地址中,即采用“大端”方式。假设在9000H开始的单元中,用

DC.W0F012H,5678H定义两个字常数,则这两个16位二进制数的存放规则是:9000H单元的内容为0F0H(高位字节),9001H单元的内容为12H(低位字节);9002H单元的内容为56H(高位字节),9003H单元的内容为78H(低位字节)。字存储单元起始于字的低位地址,对应字存储单元的高位字节。例如,在

LDWX,0100H指令中,将0100H单元内容送寄存器XH,将0101H单元内容送寄存器XL。字可以按“对齐”方式存放,字地址起始于0、2、4、6等偶字节,也可以按“非对齐”方式存放,字地址起始于1、3、5、7等奇字节。

DC.L$82000000 ;长标号(4字节,即32位整数)定义伪指令。将随后的一串32位二进制数(四

;个字节,彼此间用逗号隔开)连续存放在存储器中用于定义4字节常数表注意:不能在RAM、EEPROM段中用DC指令定义变量,原因是变量赋值只能在代码段中用“MOV”指令实现。

2) DS伪指令在ST汇编中,用DS伪指令在RAM、EEPROM存储区(段)中定义字节、字、双字变量。

DS.Bn ;保留n个字节存储单元(8位)伪指令

DS.Wn ;保留n个字存储单元(16位)伪指令

DS.Ln ;保留n个双字存储单元(32位)伪指令例如:

segment'ram1'

Data2ds.b2 ;在RAM1段内定义了字节变量Data2(预留了两个字节)在程序中,可以使用如下两种方式之一访问:

LDWX,#Data2 ;变量地址送索引寄存器X

LDA,#$5a

LD(X),A ;通过间接寻址方式访问

INCWX ; X加1,指向下一个存储单元

LD(X),A或

LDA,#$5a

LDData2,A ;用直接寻址方式读写

LD{Data2+1},A ;用直接寻址方式读写下一个单元位于RAM存储区内的字节变量最好用“标号(变量名)ds.bn”伪指令定义;字变量最好用“标号(变量名)ds.wn”伪指令定义,尽量避免用绝对标号EQU或CEQU定义。这是因为相对标号地址浮动,不会出现资源冲突,这在模块化程序中尤为重要。不过,用DS.W、DS.L定义字变量、4字节变量时均不能按字节访问,反而不方便,不如将DS.W定义的字变量用DS.B定义2个字节变量方便。例如:

VAR1DS.W1

; VAR1为字变量,只能按字方式访问改为

VAR1DS.B2 ; VAR1为字节变量,既可以按字节访问,也可以按字访问将

VAR2DS.W2 ; VAR1为字变量,只能按字方式访问改为

VAR2DS.B2MUL2 ; VAR1为字节变量,既可以按字节访问,也可以按字访问

3) END伪指令

END伪指令表示汇编结束。该指令将告诉汇编程序,下面没有需要汇编的指令。在ST汇编中,每一个模块最后一条指令必须为“END”伪指令。4.2STM8S寻址方式指令由操作码和操作数组成,确定指令中操作数在哪一个寄存器或存储单元中的方式,就称为寻址方式。对于只有操作码的指令,如NOP、TRAP等,不存在寻址方式问题;对于双操作数指令来说,每一个操作数都有自己的寻址方式。例如,在含有两个操作数的指令中,第一操作数(也称为目的操作数)有自己的寻址方式;第二操作数(又称为源操作数)也有自己的寻址方式。在现代计算机系统中,为减少指令码的长度,对于算术、逻辑运算指令,一般将第一操作数和第二操作数的运算结果经ALU数据输出口回送CPU内部数据总线,再存放到第一操作数所在的存储单元或CPU内某一个寄存器中。例如,累加器A内容(目的操作数)与某一个存储单元内容(源操作数)相加,所得的“和”将存放到累加器A中,这样就不必为运算结果指定另一个存储单元地址,缩短了指令码的长度。当然,运算后,累加器A中的原有信息(被加数)将不复存在。如果在其后的指令中还需用到指令执行前目的操作数的信息,可先将目的操作数保存到CPU内另一个寄存器或存储器的某一个存储单元中。指令中的操作数只能是下列内容之一:

(1) CPU内某一个寄存器名,如累加器A、索引寄存器X或Y、堆栈指针SP、条件码寄存器CC等。CPU内含有什么寄存器由CPU的类型决定。在STM8内核单片机CPU内,就含有累加器A、索引寄存器X和Y、堆栈指针SP、条件码寄存器CC(标志寄存器);而在MCS-51内核单片机CPU内,含有累加器A、通用寄存器B、堆栈指针SP、程序状态字寄存器PSW以及工作寄存器组R7~R0。

(2)存储单元。存储单元地址范围由CPU寻址能力及实际安装的存储器容量、连接方式决定。

(3)外设寄存器包括外设的控制寄存器、状态寄存器与数据寄存器。在STM8S系统中,与PA口有关的寄存器有PA_DDR(数据传输方向控制寄存器)、PA_CR1与PA_CR2(特性控制寄存器)、PA_ODR(输出数据锁存器)、PA_IDR(输入数据寄存器)。

(4)常数。常数类型及范围也与CPU类型有关。下面以STM8内核CPU为例,介绍在计算机系统中常见的寻址方式。4.2.1立即寻址(Immediate)当指令的第二操作数(源操作数)为8位或16位常数时,就称为立即寻址方式。其中的常数称为立即数,例如:

LDA,#$5A其中,“#”是立即寻址标识符;$5A为十六进制数5A。在立即寻址方式中,立即数包含在指令码中,取出指令码时也就取出了可以立即使用的操作数(也正因如此,该操作数被称为“立即数”,并把这种寻址方式形象地称为“立即寻址”方式)。4.2.2寄存器寻址在寄存器寻址方式中,指令中的操作数为CPU内的某一个寄存器。例如:

LDA,XL ;源操作数为CPU内索引寄存器X的低8位,属于寄存器寻址

;目的操作数为累加器A,属于寄存器寻址

LDWX,#$12 ;目的操作数为索引寄存器X,属于寄存器寻址

LDWSP,X ;源操作数为CPU内索引寄存器X,属于寄存器寻址

;目的操作数为堆栈指针SP,属于寄存器寻址在CISC指令系统中,采用寄存器寻址方式的操作数地址往往隐含在操作码字段(字节)中。其特点是,指令中的一个或两个操作数采用寄存器寻址方式,指令的机器码短。例如,“LDA,#23H”指令似乎为3个字节,实际上第一操作数A属于寄存器寻址,操作数地址隐含在操作码字段中,因此该指令机器码为B6H、23H,只有两个字节。而“LDWSP,X”指令的机器码为94H,只有一个字节,原因是该指令中的两个操作数均属寄存器寻址。

CPU内并非所有的寄存器均支持寄存器寻址,尤其是MCU内的外设寄存器,属于直接寻址而不是寄存器寻址。例如,“MOVPA_ODR,#0FFH”指令编译后与“MOV5000H,#0FFH”指令等效,即指令中的PA_ODR(PA口数据输出寄存器)操作数为直接寻址,而不是寄存器寻址。4.2.3直接寻址(Direct)在指令中直接给出操作数所在的存储单元地址。例如:

LDA,$50 ;把50H单元内容送累加器A,其中源操作数50H为存储单元地址,属于直接寻址

LDA,$5000 ;把5000H单元内容送累加器A,其中源操作数5000H为存储单元地址(16位地址)

LDFA,$015000 ;把015000H单元内容送累加器A,其中源操作数015000H为存储单元;地址(24位地址)注:在程序中,一般不宜使用直接地址,而是通过相对标号方式将其定义为一字符串,即变量名,以方便程序的维护与升级。4.2.4寄存器间接寻址在寄存器间接寻址中,操作数所在存储单元的地址存放在CPU内某一个特定寄存器中。也就是说,寄存器内容是存储单元地址。在STM8内核CPU中,索引寄存器X、Y均可作为间接寻址寄存器。例如:

LDWX,#tabdata ;其中tabdata为先前已定义过的标号

LDA,(X) ;把寄存器X内容对应的存储单元信息送累加器A

LD(Y),A ;把累加器A的内容送寄存器Y指定的存储单元指令中的“()”是间接寻址的标识符。4.2.5变址寻址(Indexed)

STM8内核CPU支持以X、Y、SP作变址的寻址方式,如

LDA,(labtab1,x)

LDA,(labtab1,y)

LDA,(labtab1,sp)

LDFA,($010000,x)其中,labtab1为标号,即基地址;x、y、sp为变址寄存器。在STM8汇编中,对于变址寻址方式,在“基址,变址”形式中,逗号( , )与变址之间不能加“空格”。例如,(LED_Data,X)是合法的地址,而(LED_Data,X)是非法的地址。该规则同样适用于复合寻址方式的地址格式,例如,([50H.W],x)是合法的复合地址,而([50H.W],x)属于非法的复合地址。例如,假设标号labtab1的地址为9000H,而变址寄存器x为120H,则“LDA,(labtab1,x)”指令的含义是把9000H + 120H = 9120H单元内容传送到寄存器A中。基地址可以是8位地址形式,即0000页内的RAM单元;16位地址形式,即00段内的RAM单元、FlashROM、EEPROM单元或外设寄存器;24位地址形式,即00~FF段内的FlashROM单元。在变址寻址方式中,标号可以用直接地址取代。实际上,在编译、连接后标号会以实际地址形式出现。这类指令编译后,指令操作码、指令长度与基地址长度、索引寄存器有关。例如:

LDA,($50,X) ;指令码为E6XX(两字节),其中E6为操作码,XX为8位基地址

LDA,($100,X) ;指令码为D6XXXX(三字节),其中D6为操作码,XXXX为16位基地址

LDA,($50,Y) ;指令码为90E6XX(三字节),其中90E6为操作码,XX为8位基地址可见,在STM8中,使用索引寄存器X的指令比使用索引寄存器Y的指令的机器码少了一个字节。源操作数支持变址寻址方式。当操作对象为RAM存储区,可随机读写的外设寄存器时,目的操作数也支持变址寻址方式。例如:

LD($50,X),A变址寻访方式在查表操作时非常有用。例如,通过变址寻址方式,可将共阳LED数码管笔段码取出。

CLRWX

LDXL,A

LDA,(LED_Data,X) ;利用变址寻址方式将累加器A内容对应的笔段码取出LED_Data: ;

0,

1,2,

3,

4,5,

6,7,

8,9,A,B,

C,D,

E,FDC.B0C0H,0F9H,0A4H,0B0H,099H,092H,082H,0F8H,080H,090H,088H,083H,0C6H,0A1H,086H,08EH当需要取出数表某一个特定项时,如第3字节,即数码3对应的笔段码时,也可用直接寻址方式实现:

LDA,{LED_Data+3} ;利用直接寻址方式将数码“3”对应的笔段码取出4.2.6以存储单元作间址的间接寻址方式以存储单元作间址的间接寻址方式是STM8CPU特有的一种间接寻址方式。操作数所在存储单元的地址存放在00段内另一个存储单元中,16位地址形式带后缀 .W;24位地址形式带后缀 .E。换句话说000000H~00FFFFH之间任意一个存储单元均可作为间接寻址单元。例如:LD[$50.W],A ;目的操作数地址存放在50H、51H单元中假设[50H,51H]=0100H,则该指令的含义是将累加器A送0100H单元中。LDFA,[$50.e] ;源操作数地址存放在50H、51H、52H单元中假设[50H,51H,52H]=010008H,则该指令的含义是将010008H单元内容送累加器A中。在源程序中,物理地址一般用某一个变量名代替。例如:var1dc.wtabled1` ;字变量var1的初值定义为tabled1,而编译后标号tabled1的值确定LD[var1.W],A ;把A送到以字变量var1内容指定的存储单元中tabled1:DC.B$03,$02不过,在00段内最好用寄存器X、Y作间址寄存器,这样代码长度会短一些。利用存储单元作为间址时,初始化间址单元需要8个字节,如下所示:MOVR00,#{HIGHtabled1} ; 4字节MOVR01,#{LOWtabled1} ; 4字节LDA,[R00.W] ; 3或4字节上述三条指令若改用寄存器X作间址,则代码短了许多,如下所示:

LDWX,#tabled1 ; 3字节

LDA,(X) ; 1字节或

LDA,(tabled1,X) ; 3字节或2字节,取决于tabled1标号的物理地址在FlashROMIAP编程指令中,一般只能使用以存储单元作间址的寻址方式,这是因为24位地址形式的FlashROM目标地址只能存放在3个RAM单元中,通过间址方式完成FlashROM字节、字、块的加载。例如,在ram0段中定义了IAP_First_ADR变量,如下所示:

IAP_First_ADR ds.b 3 则在FlashROMIAP编程指令系列中用如下指令完成加载:

LDF[IAP_First_ADR.e],A4.2.7复合寻址方式复合寻址方式是变址寻址与以存储单元作间址的寻址方式的组合,也是STM8CPU特有的一种间接寻址方式。例如:

LD([$50.W],x),A目的操作数基地址存放在50H、51H单元中,基地址内容加上变址寄存器内容就是操作数对应的存储单元的物理地址。假设 [50H,51H] = 0100H,而变址寄存器x的内容为0005H,则该指令的含义是将累加器A送0100H + 0005H = 0105H单元中。LDFA,([$9000.e],x)

24位源操作数基地址存放在9000H、9001H、9002H单元中,基地址内容加上变址寄存器内容就是操作数对应的存储单元的物理地址。假设 [9000H~9002H] = 011620H,而变址寄存器x的内容为0001H,则该指令的含义是将011620H + 0001H = 011621H单元内容送累加器A。在程序中,定义下列标号地址后,可使用如下寻址方式访问位于010000H以上单元的数表:

LDFA,([Data_ADR.e],X) ;用复合寻址方式访问

Data_ADR.W DC.B{SEGData_TAB},{HIGHData_TAB},{LOWData_TAB}

Data_TAB.L ;数表

DC.B05H,07H,…,4.2.8相对寻址相对寻址的含义是,以程序计数器PC的当前值加上指令中给出的相对偏移量rel作为程序计数器PC的值。这种寻址方式用在条件转移指令中,如

JRCnext 其中,next为目标地址标号,其含义是如果进位标志C为1,则转到next处执行。4.2.9隐含寻址隐含寻址也称为固有寻址。有些指令操作码约定使用特定的操作数,如RIM指令(开中断)的操作对象默认为中断优先级标志位,即操作码9AH(RIM指令操作码)指令的操作数固定为I1、I0。换句话说,指令操作数隐含在操作码字段中。例如:

MULX,A ;

X←XL

×

A该指令码为42H(单字节),似乎只有操作码42H,没有操作数。实际上,在字节乘法指令中,操作数固定为XL(被乘数)、A(乘数),无须在指令码中给出操作数地址。4.2.2节介绍的寄存器寻址就属于隐含寻址范畴。例如:

PUSHA ; (SP)←A,SP←SP + 1指令码为88H(单字节),其操作数A隐含在操作码字节中。

LDA,20H ;将20H单元内容送累加器A中该指令码似乎为三个字节,但指令码为B6H、50H,只有两个字节,原因是操作数A隐含在操作码字节中。4.2.10位寻址

MCU芯片一般均提供位操作指令,以方便位操作。STM8内核CPU中00段内任意一个存储单元均可按位寻址。例如:

BTJT200H,#2,NEXT ;若200H单元的b2位为1转移,位测试

BSET200H,#2 ;将200H单元的b2位置1,位置1

BRES200H,#2 ;将200H单元的b2位清0,位清0

BCPL200H,#2 ;将200H单元的b2位取反(b2←),位取反4.3STM8S指令系统4.3.1数据传送(LoadandTransfer)指令数据传送是计算机系统中最常见、最基本的操作。数据传送指令在计算机指令系统中占有非常重要的位置,指令条数众多,其任务是实现计算机系统内不同存储单元之间的信息传送,如图4-1所示。图4-1STM8内核CPU不同存储区之间数据传送示意图由此可见:

(1)在STM8中,立即数不能直接送堆栈指针SP,当需要初始化堆栈指针SP时,只能先将16位立即数送寄存器X或Y,再将寄存器X或Y的内容送SP。

(2)尽管寄存器X、Y分别由两个8位寄存器组成,但不能直接将8位立即数送XL、XH、YL、YH中,换句话说“LDXL,#XX”指令不存在。

(3)在数据传送指令中,当源操作数或目的操作数之一为CPU内某一个寄存器(A、X、Y)时,使用LD(字节)、LDW(字)指令、LDF(24位地址形式的字节传送);当源操作数和目的操作数均不含寄存器A、X、Y时,使用MOV指令(字节传送)。因此,字(16位)存储单元之间不能直接传送。

(4)数据传送指令一般不影响条件码寄存器CC中的标志位,仅影响N(负号)、Z(零)标志,如表4-2所示。表4-2数据传送指令对标志位的影响

(1)堆栈操作指令一般不影响标志位,除非指令将堆栈内容弹到条件码寄存器CC本身,即只有“POPCC”指令才影响标志位。

(2)在LD、LDW指令中,CPU内核寄存器之间的数据传送指令不影响任何标志位。

(3)数据交换指令EXG、EXGW指令也不影响标志位。例如:

LDA,XL ;执行后对CC寄存器没有任何影响

(4) MOV数据传送指令不影响任何标志位。例如:MOV50H,#55H ;执行后对CC寄存器没有任何影响MOV50H,100H ;执行后对CC寄存器没有任何影响

(5)在LD、LDF、LDW、MOV、SWAP指令中,当写入或清除对象为存储单元时,在非IAP编程装载状态下,不能是EEPROM、FlashROM存储区,原因是EEPROM、FlashROM只读,不能随机写入。例如:

MOV100H,#55H ;写入对象为RAM单元,合理

MOV9000H,#55H ;写入对象为FlashROM存储单元,在非IAP编程装载状态下无效

LD9000H,A ;写入对象为FlashROM存储单元,在非IAP编程装载状态下无效

1. LD指令(字节装载指令)

LD字节装载指令的格式、机器码以及执行时间如表4-3所示。表4-3LD字节装载指令的格式、机器码以及执行时间

例4-1

在STVD开发环境下,用单步方式执行下列指令,观察指令执行前后,相关RAM单元内容和条件码寄存器CC中V、I1、H、I0、N、Z、C等标志位的变化,了解数据传送指令对标志位的影响。

MOV30H,#01H ;把立即数01H传送到30H单元

LDA,#5AH ;把立即数5AH送累加器A

LDA,30H ; 30H单元内容送累加器A

LDXL,A ;累加器A送索引寄存器X的低8位XL

2. LDW指令(字装载指令)

LDW字装载指令的格式、机器码以及执行时间如表4-4所示。表4-4LDW字装载指令的格式、机器码以及执行时间

(1)在STM8内核CPU中,字(16位)传送指令非常丰富,但也并非所有寻址方式的组合都属于有效指令。例如,在X、Y与(X)、(Y)组合的字传送指令中似乎有12种组合,但只有表4-4中给出的4种有效组合,而其他组合,如“LDW(X),X”指令并不存在,即非法指令。

(2)寻址方式越复杂,指令的执行时间就越长。因此,在指令中尽可能避免使用复杂寻址方式。

3. LDF指令(24位地址形式的字节装载指令)

LDF字节装载指令的格式、机器码以及执行时间如表4-5所示。表4-5LDF字节装载指令的格式、机器码以及执行时间

4. MOV指令(字节传送指令)

MOV字节传送指令的格式、机器码以及执行时间如表4-6所示。表4-6MOV字节传送指令的格式、机器码以及执行时间

(1)利用MOV指令,可对00段内任意一个存储单元进行赋值。例如:

MOV2FH,#$55 ;把55H立即传送到2FH单元中该指令与“MOV002FH,#$55”等效。

MOV20H,34H ;把00页内的34H单元内容送到00页内的20H单元该指令为3个字节。

MOV20H,1034H ;把00段内的1034H单元内容送到00页内的20H单元该指令为5个字节。在MOV指令中,若两个存储单元地址中任意一个单元地址在00页以外,则两个操作数均采用16位地址形式。

(2) MOV指令中的存储单元仅支持直接寻址方式,不支持间接、变址等其他寻址方式。

(3)对EEPROM、FlashROM存储区可进行读操作,但不能对其进行写操作。例如:

MOV$1000,$9000 ; (1000H)(RAM存储区)←(9000H)(FlashROM)属合法指令。而MOV$9000,$1000 ; (9000H)(FlashROM存储区)←(1000H)(RAM)在非IAP编程装载状态下属非法指令,编译时没有给出警告信息,而执行时后果难料。

(4) MOV指令不支持01及以上段存储单元的读写操作,原因是STM8CPU最长指令码为5字节。

5. EXG指令(字节交换)与EXGW(X与Y交换)

EXG字节交换指令的格式、机器码以及执行时间如表4-7所示。交换与传送的区别在于交换后目的操作数与源操作数内容对调,并没有覆盖目的操作数原来的内容。表4-7EXG字节交换指令与EXGW字交换指令的格式、机器码以及执行时间

尽管在交换指令中,“A与XL交换”和“XL与A”交换效果相同,但却没有“EXGXL,A”指令,A也不能与XH或YH交换,原因是内部硬件连线不支持。累加器A可以与00段内任意一个存储单元(16位直接地址形式)交换。例4-2假设累加器A的内容为55H,XL的内容为0AAH,则执行

EXGA,XL指令后,累加器A的内容为0AAH,XL的内容为55H,即A和XL的内容交换了。这与数据传送指令不同,数据传送指令执行后,源操作数的内容覆盖了目的操作数原来的内容。

6. SWAP指令(半字节交换)与SWAPW(X或Y高低字节对调)指令半字节交换指令SWAP与EXG指令不同,执行SWAP指令后,指令中给定操作数(字节)的高4位与低4位对调。例如,假设(10H)单元为5AH,则执行

SWAP$10指令后,(10H)单元变为A5H。同理,执行“SWAPWX”指令后,寄存器X的高8位与低8位对调。

SWAP半字节交换指令与SWAPW字节交换指令格式、机器码以及执行时间如表4-8所示。表4-8SWAP(半字节)与SWAPW(字节)交换指令格式、机器码以及执行时间

7.堆栈操作指令堆栈操作是计算机系统基本操作之一。设置堆栈操作的目的是为了迅速保护断点和现场,以便在子程序或中断服务子程序运行结束后,能正确返回主程序。STM8内核CPU堆栈操作指令包括字节(8位)入堆操作PUSH指令、字(16位)入堆操作PUSHW指令,以及与之对应的字节出堆操作指令POP、字出堆操作指令POPW。这些指令的格式、机器码、执行时间如表4-9所示。表4-9堆栈操作指令格式、机器码以及执行时间有关STM8内核CPU堆栈操作的过程,已在第2章介绍过,这里只强调堆栈操作应注意的问题:

(1)在子程序开始处安排若干条PUSH指令,把需要保护的寄存器内容(累加器A、条件码寄存器CC、索引寄存器X和Y)压入堆栈,在子程序返回指令前,安排相应的POP指令,将寄存器原来内容弹出。PUSH和POP指令必须成对存在,且入栈顺序与出栈顺序相反,子程序结构如下:PUSH CC ;保护现场PUSH A

;子程序实体POP A ;恢复现场POP CCRET ;子程序返回

(2)在STM8内核CPU的中断服务程序中,无须借助“PUSHA”、“PUSHWX”之类的指令保护现场,这是因为STM8内核CPU响应中断请求后,自动将CPU内寄存器压入堆栈。从数据传送指令中可以看出:CPU内寄存器A、X、Y及存储单元之间的数据传送指令一般仅需要一个机器周期,即从执行时间的角度看,任意一个RAM单元均可作为CPU内寄存器使用。4.3.2算术运算(Arithmeticoperations)指令

STM8S提供了丰富的算术运算指令,具有较强的数值处理能力,包括三条加法运算指令:不带进位字节加法指令ADD,带进位字节加法指令ADC,不带进位字加法指令ADDW;三条减法运算指令:不带借位字节减法指令SUB,带借位字节减法指令SBC,不带借位字减法指令SUBW;增1指令:字节增量指令和字增量指令;减1指令:字节减量指令和字减量指令;以及8位乘法指令、16位除法指令等。一般情况下,算术运算指令执行后会影响条件码寄存器CC中除I1、I0位外所有的标志位,如表4-10所示。表4-10算术运算指令对标志位的影响

1.加法指令

STM8CPU加法指令操作码助记符、指令格式、机器码以及指令的执行时间如表4-11所示。表4-11STM8内核CPU加法指令由表4-11可以看出:

(1) ADD、ADC加法指令的目的操作数一般为累加器A,源操作数支持寄存器、直接、寄存器间接、立即数、变址等多钟寻址方式。加数(源操作数)可以是000000H~FFFFFFH的存储单元。但STM8CPU内两个寄存器之间不能直接相加,如“ADDA,XL”、“ADDWX,Y”指令不存在。

(2)在STM8指令系统中,有一条特殊的16位加法指令和一条特殊的16位减法指令。

ADDWSP,#Byte ; SP←SP+#Byte(8位立即数)

SUBWSP,#Byte ; SP←SP-#Byte(8位立即数)这两条指令主要用于迅速将SP指针上下移动指定的偏移量,并不是为了进行加法或减法运算,因此,这两指令执行后不影响CC寄存器中的标志位。

(3)加法指令执行后将影响进位标志C、溢出标志V、半进位标志H、零标志Z、负号标志N。若相加后b7位有进位,则C为1;反之为0。b7有进位,表示两个无符号数相加时,结果大于255,和的低8位存放在累加器A中,即C =其中,A7表示运算前累加器A的b7位;M7表示运算前存储单元的b7位;R7表示运算结果的b7位。

CPU并不知道参加运算的两个数是无符号数,还是有符号数,程序员只能借助溢出标志V来判别带符号数相加是否溢出。对于带符号数来说,b7是符号位,b7为0表示正数,b7为1表示负数,且负数为补码形式。于是,当两个正数相加时,如果累加器A的b7为1,表示结果不可能是负数,即和大于 +127;同理,当两个负数相加时,如果累加器A的b7为0,表示结果不可能是正数,即和小于 -128。在加法指令中,溢出标志V置1的条件是:两个操作数的符号相同,即b7位同为0或1,但结果的符号位相反,即V =对于带符号数加法运算来说,当溢出标志V为1,表示结果不正确。若相加后b3位向b4位进位,则H为1;反之为0,即H =当运算结果为0时,Z = 1。当运算结果的最高位为0,对8位来说b7 = 0,对16位来说b15 = 0,则标志N = 0。

(4)带进位加法指令中的累加器A除了加源操作数外,还需要加上条件码寄存器CC中的进位标志C。设置带进位加法指令的目的是为了实现多字节加法运算。例4-3

将存放在30H、31H单元中的16位二进制数与存放在32H、33H单元中的16位二进制数相加,假设结果存放在30H、31H中。

LD A,$31 ;将被加数低8位送寄存器A中

ADD A,$33 ;与加数低8位(33H单元内容)相加,结果存放在A中

LD $31,A ;将和的低8位保存到31H单元中

LD A,$30 ;将被加数高8位送寄存器A中

ADC A,$32 ;与加数高8位(32H单元内容)相加,结果存放在A中

;由于低8位相加时,结果可能大于0FFH,产生进位,因此高8位

;相加时用ADC指令

LD $30,A ;将和的高8位保存到30H单元中

STM8内核CPU具有16位加法指令,可直接使用ADDW指令完成上面的计算,不仅指令代码短,执行时间也相应缩短,如

LDWX,30H ;把16位被加数送寄存器X

ADDWX,32H ;与16位加数相加

LDW30H,X ;结果送30H、31H单元中在“ADDWX,mem”、“ADDWY,mem”指令中,当b15有进位时,C标志为1;当b7向b8进位时,半进位H标志为1。

(5) STM8内核CPU没有BCD码调整指令“DAA”,对于BCD相加只能先转化为二进制后再相加。

2.减法指令

STM8内核CPU减法指令操作码助记符、指令格式、机器码以及指令的执行时间如表4-12所示。表4-12STM8内核CPU减法指令续表

STM8减法指令与加法指令类似,操作结果同样会影响标志位。

(1) C为1,表示被减数小于减数,产生借位。

(2) V同样用于判别两个带符号数相减后,差是否超出8位带符号数所能表示的范围(-128~+127)。当两个异号数相减时,差的符号与被减数相反,则溢出标志V为1,结果不正确。例如,被减数为正数,减数为负数,相减后的结果应该是正数,但如果累加器A的b7为1,即负数,则表明结果不正确。

(3)如果相减时b3位向b4位借位,则H标志1;反之为0。

(4)当运算结果为0时,Z = 1。

(5)当运算结果最高位为0,对8位来说b7 = 0,对16位来说b15 = 0,则标志N = 0。字节减法指令SUB、SBC不影响半进位标志H,即在STM8系统中,不能通过减法指令完成BCD码的减法运算。字减法运算指令会影响H标志,当b7向b8借位时,H标志为1。例4-4用减法指令求存放在RAM单元中两数的差值。假设被减数存放在30H单元中,减数存放在31H单元中,差放在40H单元中。

LD A,$30 ;被减数送寄存器A

SUB A,$31 ;减去31H单元中的减数

LD $40,A ;结果保存到40H单元中

3.乘法指令

STM8S提供了两条8位无符号数乘法指令,其操作码助记符、指令格式、机器码以及执行时间如表4-13所示。表4-13乘法指令格式、机器码以及执行时间对于MULX,A指令来说,8位无符号数被乘数放在索引寄存器X的低8位XL中,忽略高8位XH,乘数放在累加器A(8位无符号数)中,乘积(16位无符号数)存放在索引寄存器X中。对于MULY,A指令来说,8位无符号数被乘数放在索引寄存器Y的低8位YL中,忽略高8位YH,乘数放在累加器A(8位无符号数)中,乘积(16位无符号数)存放在索引寄存器Y中。乘法指令影响标志位:进位标志C与半进位标志H总为0,而其他位保持不变,不受影响。

STM8CPU没有提供8位 × 16位、16位 × 16位、16位 × 24位等多字节乘法指令,只能通过单字节乘法指令实现多字节乘法运算,可采用图4-2所示算法实现相应的多字节乘法运算。图4-2多字节乘法算法在16位乘8位运算中,16位被乘数占2字节,用BA表示;8位乘数占1字节,用C表示,则乘积为24位。显然“A*C”为16位,“B*C”为24位。因此,可用图4-2(a)所示算法实现。在16位乘16位运算中,16位被乘数占2字节,用BA表示;16位乘数也占2字节,用DC表示,则乘积为32位。显然“A*C”为16位,“B*C”为24位;“A*D”为24位,“B*D”为32位。因此,可用图4-2(b)所示算法实现。在24位乘16位运算中,24位被乘数占3字节,用CBA表示;16位乘数占2字节,用ED表示,乘积应该为40位。显然“A*D”为16位,“B*D”为24位,“C*D”为32位;“A*E”为24位,“B*D”为32位,“E*C”为40位。因此,可用图4-2(c)所示算法实现。例4-5

编写一个程序段,实现16位 × 8位运算。

MUL1608:

; 16bit*8bit运算程序

;入口参数:16位被乘数存放R01~R02中(高位放在低地址)

;  :8位乘数存放在R00中

;出口参数:24位乘积存放在R03~R05中(高位放在低地址)

;算法:多字节乘法运算规则

;执行时间为21个机器周期

;使用资源A、XCLRR03 ;清除乘积最高位(b23~b16);计算低8位相乘LDA,R02 ;取被乘数的低8位LDXL,ALDA,R00 ;取8位乘数MULX,A LDWR04,X ; 16位乘积送R04、R05中;计算高8位相乘LDA,R01 ;取被乘数的高8位LDXL,ALDA,R00 ;取8位乘数MULX,A

;求和ADDWX,R03 ;与[AC]H相加LDWR03,X ;保存结果RET以上程序段代码并不长,执行时间也仅为21个机器周期。例4-6编写一个程序段,实现16位 × 16位运算。

segment'ram0'

Bytes ;执行ram0段内的变量标号为字节标号

R00DS.B1

R01DS.B1

R02DS.B1

R03DS.B1

R04DS.B1

R05DS.B1

R06DS.B1

R07DS.B1MUL1616:;

16bit*16bit运算程序;入口参数:

16位被乘数存放R00~R01中(高位放在低地址); 16位乘数存放在R02~R03中(高位放在低地址);出口参数:32位乘积存放在R04~R07中(高位放在低地址);算法:多字节乘法运算;执行时间为45个机器周期;使用资源A、XCLRR04 ;清除乘积高16位(b31~b16)存放单元CLRR05;CLRR06 ;由于用字传送指令,将低8位乘低8位的结果直接送R06、R07单元,

;因此不必先清零;CLRR07LDA,R01 ;取被乘数的低8位LDXL,A ;送寄存器XLLDA,R03 ;取乘数的低8位MULX,A ;计算ACLDWR06,X ;保存AC的结果;计算BCLDA,R00 ;取被乘数的高8位LDXL,A ;送寄存器XLLDA,R03 ;取乘数的低8位MULX,A ;计算BCADDWX,R05 ;计算机([AC]H,[AC]L)

+

([BC]H,[BC]L)LDWR05,X; 16位乘8位,结果为24位,不可能产生进位;计算ADLDA,R01 ;取被乘数的低8位LDXL,A ;送寄存器XLLDA,R02 ;取乘数的高8位MULX,A ;计算ADADDWX,R05 ;求和LDWR05,XBCCMR04,#0 ;用BCCM指令将进位标志送R04单元的b0位,代替下面三条指令

;可减少2个机器周期;CLRA ;清除A;ADCA,R04 ;加进位标志C;LDR04,A;计算BDLDA,R00 ;取被乘数的高8位LDXL,A ;送寄存器XL

LDA,R02 ;取乘数的高8位

MULX,A ;计算AD

ADDWX,R04 ;求和

LDWR04,X ;保存和。不可能产生进位

RET可见,在STM8中充分利用16位加法指令ADDW、16位数据传送指令LDW,完成多字节乘法运算用时并不多,例4-6所示仅用45个机器周期。

4.除法指令

STM8提供了16位除8位、16位除16位无符号数除法指令,其操作码助记符、指令格式、机器码等如表4-14所示。表4-14STM8CPU除法指令除法指令影响标志位:溢出标志V、半进位标志H、负数标志N总为0;零标志

Z—商为0时,Z置1;进位标志C—除数为0时,C为1,即借用了进位标志C指示除数是否为0。对于16位除8位指令,如“DIVX,A”,商为16位,余数为8位,显然余数取值范围在0~[除数 -1]之间。对于16位除16位指令“DIVX,Y”来说,商为16位,余数也是16位。对于更多位除法运算,如32位除16位等多位除法运算,可借助减法或类似多项式除法运算规则完成。用减法实现除法运算的原理是:先用被除数减去除数,够减则商为1,反之则为0;再循环使用差减除数,够减商加1,直到不够减为止。当除数远远小于被除数时,执行时间可能偏长。用类似多项式除法运算规则完成除法运算的时间是固定的,与除数大小无关。例4-7利用16位除法指令,将16位二进制数转换为非压缩形式的BCD码。

BIN_BCD: ;二进制→BCD码

;算法:由于STM8CPU具有16除法指令,因此:

;万位BCD = 二进制数/10000

;千位

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论