《第3节指令系统.ppt》由会员分享,可在线阅读,更多相关《第3节指令系统.ppt(65页珍藏版)》请在优知文库上搜索。
1、Freescale 8位单片机指令系统HCS08 CPU指令表HCS08指令系统共有120条基本指令,每一条指令又有各自不同的寻址方式,根据这些基本指令的功能,现将其分为以下六类:算术算术运算运算数据数据传送传送逻辑逻辑操作操作程序程序控制控制移位类移位类指令指令指令系统分类指令系统分类位操作位操作数据传送指令数据传送指令这组指令用于存储器和CPU 寄存器间、存储器单元间或者CPU 寄存器间的数据转移。读入、存储和数据传送等指令根据数据的值自动更新条件码自动更新条件码。这允许BEQ、BNE、BPL 和BMI 等在载入、储存和数据传送指令后不需要运行特殊的测试或比较指令,而立即进行条件转移。Lo
2、ad A 和Load X是从存储器中取出一个8位数放入累加器A或寄存器X。Load H:X是从存储器中取出8位的数放入寄存器H,然后再从下一个存储单元取出8位数放入寄存器X。为了尽可能灵活的访问存储器,加载A 或X 都可使用8 种不同的寻址方式。而LDHX 可有7种不同的寻址方式来指定所取数的存储单元。下列代码展示了加载指令的某些用法。这些指令在实际程序中并不这样用,它们只是些无关联的加载指令,用来说明可用不同方式来访问存储器的多种可行的寻址方式.因为操作数进入ALU 需要用到累加器A,所以通常在执行算术与逻辑操作时,要使用LDA 指令取得一个值,以便与第2 个操作数进行运算。;求A+B的和(
3、假设总和累加器add oprB;立即数A+立即数B-累加器在有些情况下,可设计程序使得放在累加器A 中的运算结果能用来作为后续运算的操作数。这样可以避免存储结果的过程以及将下一个操作数放入累加器的必要。;求A+B+C的和(假设总和累加器add oprB ;立即数A+立即数B-累加器add oprC ;累加器+立即数C-累加器下面展示了中间值保存在堆栈中的例程。有时这样做比将临时结果存储在存储器中要快。存储的数量依赖于用何种寻址方式放置临时变量至存储器以及X 寄存器是否被其他操作所使用.;计算(A+B)-(C+D)(假设没有进位或借位)LDA oprC ;立即数C-累加器ADD oprD ;立即
4、数C+立即数D-累加器PSHA ;中间结果放入堆栈SP+1LDA oprA ;立即数A-累加器ADD oprB ;立即数A+立即数B-累加器SUB 1,sp ;(A+B)-(C+D)结果放入累加器AIS#1 ;释放一个变量TAX 和TXA 提供了一个有效的方法来把A 寄存器的值送到X 寄存器或者把寄存器X 的值送到寄存器A。如果寄存器X 未被使用,可以用来暂存累加器A 中的值,这样累加器就可以用来做其他操作。TAP 和TPA 提供了一个方法在寄存器A 到CCR 中或者从CCR 到寄存器A 传送数据。这种操作在类似调试监控等开发工具中比在通常用户程序中使用得更多。MOV指令从存储器区读一个8 位
5、数值,并将这个数值存储到存储区的其他地方。就像加载和存储指令一样,MOV 根据被移动数据的值改变CCR 中N 和和Z 标志位。尽管加载和存储指令能够完成尽管加载和存储指令能够完成MOV 所做的事情,但MOV 不需要使用累加器,在传送操作期间,累加器A 能够正常使用。在许多情况下,MOV 比加载-存储指令更快更小(目标代码的大小)。MOV 指令允许四种从指定源到目标的不同的寻址方式。下面的例子展示了使用传送指令初始化几个寄存器的值。284 C0DB 6E 03 00 mov#$03,PTAD ;0011到低4位285 C0DE 6E 0F 03 mov#$0F,PTADD ;使得低4位为输出28
6、6 C0E1 6E F0 01 mov#$F0,PTAPE ;上拉高4位下面例子展示了使用加载和存储指令实现字符串移动字符串移动操作数,而不用传送指令。;块移动例子,移动字符串到RAM块45 0088 LDHX#moveBlk1;指向RAM目标块D6 BF7F movLoop1:LDA(stringBytes-moveBlk1),x;得到源字节27 04 BEQ dunLoop1;结束循环的条件F7 STA ,x ;保存到目标块5C INCX ;下一个位置(假设直接寻址)20 F7 BRA movLoop1;继续循环 dunLoop1:算术运算指令算术运算指令包含了传统的加、减、乘和除操作,还
7、包含常用的指令如加一、减一、清零、求补(2 进制补码)、比较、测试和为处理BCD 码的十进制调整指令。比较指令实际上就是减操作,影响CCR 状态位但结果不返回到CPU 寄存器。测试指令影响着N和Z 位,但是不影响被测试的数据。ADD 指令将寄存器A 中的数据加上存储器内的操作数,并将结果存储到寄存器A中。ADC 将寄存器A 中的数据加上由前一次操作产生的进位,再加上存储器中的操作数,将结果存储到寄存器A 中。该操作允许执行多字节加法,就像下例所示。;8位操作数到24位和的加法LDA oprA ;取8位操作数到寄存器AADD sum24+2 ;24位和的低字节STA sum24+2 ;更新24位
8、和的低字节LDA sum24+1 ;取24位和的中间字节ADC#0 ;保持任何进位STA sum24+1 ;更新中间字节LDA sum24 ;得到24位和的高字节ADC#0 ;保持进位到高字节中STA sum24 ;更新高字节SUB 指令将累加器A 中的数据减去存储器中的数据,然后将结果存储到累加器A中。对于这个指令,进位状态位是借位指示器。SBC 指令将累加器A 中的数据减去由前一次操作所影响的借位再减去存储器中的数据,然后将结果存储回寄存器A 中。这个操作允许执行多字节减法,就像下面例子所显示的。;16位减法.结果是16位=oprE-oprFLDA oprE+1 ;oprE的低8字节SUB
9、 oprF+1 ;oprE(低字节)-oprF(低字节)STA result16+1;结果的低字节LDA oprE ;oprE的高字节SBC oprF ;oprE(高字节)-oprF(高字节)-借位STA result16 ;结果的高字节MUL 指令将寄存器X中无符号8位2进制数与累加器A中的无符号的8 位2进制数相乘,然后存储16位结果到X:A 中,高8 位的结果存储在X中,低8位存储在A中。这种情况下不可能发生进位(或者是溢出),其结果将总是适合X:A 的大小。因此在这个操作后C 将被清零。DIV 将H:A 中16 位无符号数除以X中无符号的8位值,然后存储8位结果到A寄存器中,余数存储到
10、H寄存器中。在X中的除数无变化,因此他能够在随后的操作中被使用。如果商为0则Z标志被置1。如果商大于255 就会有溢出发生,如果发生溢出或除数为0 则C 位被置1。下面这个除法的例子展示了简单8 位除以8 位得到一个8 位的结果。;8/8整数除法.A=A/XCLRH ;清零被除数高字节LDA divid8 ;加载8位被除数LDX divisor ;加载除数DIV ;H:A/X-A,余数-HSTA quotient8 ;保存结果另一个除法的例子证明了怎样使用DIV 指令来执行一个8 位到8 位的除法,并得到小数部分的结果(可以精确到小数点后8 位)。;8/8 整数除法,将余数变为8位的小数位;r
11、8.f8=A/X,将余数变为8位的小数位;16位的结果-(8位整数).(8位小数)CLRH;清零被除数的高字节LDA divid8;加载8位被除数LDX divisor;加载除数DIV;H:A/X-A,余数-HSTA quotient16;结果的高字节保存整数部分CLRA;H:A=余数:0DIV;H:A/X-ASTA quotient16+1;低字节放小数部分第三个除法的例子。用一个8 位的被除数来除一个大于8 位的除数得到16 位的小数结果,小数点在结果最高位的左边。在二进制中,MSB 的数值是整个数值的一半,右边的下一位占四分之一,依次类推。;8/8小数除法,16位的小数结果;r16=H/
12、X,结果是一个16位的二进制小数;在H和X中,假设基数是在相同的位置;16位的结果-.(16位的小数);除数和被除数都被定义了,因此用ldhx加载H和XCLRA;清零LS字节的被除数LDHX divid8;H:X=被除数:除数DIV;H:A/X-A,余数-HSTA quotient16;结果的高字节CLRA;H:A=余数:0DIV;H:A/X-ASTA quotient16+1;结果的低字节第四个除法例子使用了类似长除法的技术,完成16 位整数除以8 位的数的操作.;极大的16/8整数除法(相当于长除法);r16.f8=H:A/X,结果是16位整数,8位二进制小数CLRH;清零被除数的高字节L
13、DA divid16;被除数的高字节LDX divisor;装载除数DIV;H:A/X-A,余数-HSTA quotient24;结果的高字节LDA divid16+1;H:A=余数:被除数(低字节)DIV;H:A/X-A,余数-HSTA quotient24+1;结果的下一个字节CLRA;H:A=余数:0DIV;H:A/X-ASTA quotient24+2;结果的小数位第五个例子展示了通过检查溢出来实现16 位数除以8 位数的操作。;有限的16/8整数除法(带溢出检查);r8=H:A/X,结果是8位的整数LDHX divid16;H:X=16位的被除数TXA;H:A=16位的被除数LDX
14、divisor;X=8位的除数DIV;H:A/X-A,余数-HBCS divOvrflow;是否溢出STA quotient8;结果的高字节divOvrflow:;溢出转到这里加一、减一、清零和求补加一、减一、清零和求补 加一与减一指令可以通过加1 或减1 调整寄存器A、X 或存储器或存储器内的数据。清零指令可以将寄存器A、X、H 或者存储器中的8 位数值强制改为0。求补指令执行了二进制补码操作,求补指令等同于将一个8 位有符号数乘以-1。功能上等同于将寄存器A、X 或者存储器中的数据全部全部取反,然后加上一取反,然后加上一。数据$80 表示有符号数值负128,而不是+128。因为使用8 位2
15、 进制补码所能表示的最大是+127。如果寄存器的值是$80 然后若执行NEGA 指令,CPU 首先反转所有的位获得$7F,然后再加1 得$80。因为这个原因如果一个数据的符号由正变负,在CCR 中的V 标志位将标示为溢出错误。比较和测试比较和测试CMP 指令影响CCR 的位,就像相应的SUB 指令。但其结果不会存储回累加器中,因此A 寄存器和存储器操作数是不发生变化的。比较指令是比较寄存器A、X 或H:X内容与存储器中的操作数。在CPHX 指令执行时,M 指向存储位置的首地址,H 与存储器位置M 相对应,X 和存储器位置M+1 相对应。CPHX 执行一个16 位减法指令(存储结果不返回H:X
16、中)。测试指令是将寄存器A、X 或者存储器中的操作数与0 相减。这个操作清零了V,然后依据测试的结果置位或者清零N 和Z,依据在测试指令的结果而定。测试指令不改变测试数的值。BCD的计算的计算在BCD 码数值中,16 进制数表示一个有符号的十进制数值0 到9。当两个8 位的BCD 数值相加,CPU 实际上执行普通的二进制加法。对于BCD 码,这个计算的结果可能不再是一个有效的BCD 码。根据ADD 或ADC 指令对2 个标准的BCD 数计算所改变的H 和和C 标志位标志位,DAA 指令可以对结果进行修正使其成为有效的有效的BCD 数并且修正数并且修正C 标志位的内容使其正确的表示使用BCD 加法后的结果。在过去完成这些操作是非常复杂的,需要测试每一个BCD 数值的结果和H、C 标志位。而DAA 指令则能很简单的完成这个操作。下面例子展示了2 种可能的情况:当2 个8 位BCD 数据相加,并且使用DAA 指令对其进行修正,以修正BCD 和设置进位标志位。第一个例子展示了一种情况,BCD码加法后结果不需要调整。第二个例子展示了另一种情况,BCD 码加法后需要对结果调整。在第二个例子中DAA