第五章 AVR单片机浮点数运算程序设计.docx
《第五章 AVR单片机浮点数运算程序设计.docx》由会员分享,可在线阅读,更多相关《第五章 AVR单片机浮点数运算程序设计.docx(25页珍藏版)》请在冰豆网上搜索。
第五章AVR单片机浮点数运算程序设计
第五章浮点数运算程序设计
5.1四字节浮点格式
进行数值运算时,采用定点数运算往往不能满足要求。
例短整数(8位带符号数)表示数的范围为-128~+127;整数(16位带符号数)表示数的范围为-32768~+32767;长整数(32位带符号数)表示数的范围为-231~(231-1)。
每增加或减少1个数字单位恒为1,这样在绝对值很小的时候,表示的数的精度就很低。
为了满足数的范围和精度的要求,常采用浮点数的格式。
二进制浮点数一般采用±M×2E的形式表示。
其中M为尾数,是定点数(无符号数),±为数符,E为指数。
若用1位二进制数表示符号位,0为正,1为负;
24位二进制数表示尾数0.100……0~0.111……1
8位二进制数表示指数,取-125~+128
则表示数的范围就可以扩大为±(0.5×2-125~1.0×2128)
即±(1.2×10-38~3.4×1038),精度为2-24即5.9×10-8。
我们采用的IEEE提出的四字节浮点数标准,恰好能很好表示这个范围的浮点数,其格式为:
最高位(第31位)为数符位,0为正,1为负;低23位(0~22位)为尾数,实际尾数为
0.100……0~0.111……1
第23~30位这8位为阶码。
由于指数取值范围为-125~+128,可正可负,为简单起见,阶码采用指数的移码,阶码=指数+$7E。
这样阶码恒为正。
阶码为0即浮点数为0(小于1.2×10-38);
阶码为$78,指数为$78-$7E=-6;
阶码为$88,指数为$88-$7E=10;
阶码为$FF,指数为$ff-$7E=$81超出四字节浮点数的表示范围,表示溢出(即绝对值大于3.4*1038)。
为了方便理解该符点数的格式,下面举几个实际例子。
例:
十进制数1=0.5*21,数符为0;阶码为1+$7E=$7F;
尾数0.5=0.100……0b,去掉最高位1,00……0(23位);
四字节浮点数为0011111110……0b即为$3F800000
例:
0.5=0.5*20,数符为0;阶码为$7E;尾数去掉最高位1为0000……0b(23位);
四字节浮点数为001111110000……0b即为$3F000000。
例:
-5=-101=-0.101*23
数符为1;阶码为3+$7E=$81;尾数去掉最高位1为0100……0b(23位);
四字节浮点数为1100000010100000……0b即为$C0A00000。
5.2四字节浮点运算子程序库——AVR32FP.INC
该浮点运算子程序主要有最基本的数值计算(加、减、乘、除运算)和整数到浮点、浮点到整数的转换。
该浮点运算子程序库占353个字。
共使用寄存器16个并使用了SRAM五个字节。
注意:
调用加减乘除子程序前必须将Y寄存器置初值,使用的SRAM五个字节的地址为Y-5、Y-4、Y-3、Y-2、Y-1。
且应使这五个字节与堆栈区和SRAM其它工作区不要重复。
浮点运算子程序库中包含以下八个子程序:
INT2FP—16位整数转换成四字节浮点数运算子程
LONG2FP—32位长整数转换成四字节浮点数运算子程
FP2INT—四字节浮点数转换成16位整数运算子程
FP2LONG—四字节浮点数转换成32位长整数运算子程
ADD32F—四字节浮点加法运算子程
SUB32F—四字节浮点减法运算子程
DIV32F—四字节浮点除法运算子程
MPY32F—四字节浮点乘法运算子程
由于这八个浮点子程序都是常用的。
所以将这些子程序编写在一块,各有自己的入口,又有一些共同的程序段。
这样编写可以节省程序存储单元,浮点程序库总共只占353个字,还不到AT90S8535内部Flash的十分之一,一般不至于影响存放用户程序。
以下简单介绍一下各浮点子程序的程序思想:
1.定点长整数(或整数)转换成浮点数:
若为整数先将其转换成长整数(正数高16位添0,负数高16位添1);取出符号位及绝对值(正数绝对值不变,负数绝对值取补);将31位绝对值左移至最高位为1,其后23位数即为浮点数尾数(不足23位用0补足);浮点数的阶码为$9d减去左移次数。
2.浮点数取长整(或取整):
先判断阶码是否小于$7f,若小于$7f则结果为0;再看阶码是否大于$9d(或$8d),若大于则溢出,正数取$7fffffff(或$7fff),负数取$80000000(或$8000);否则尾数最高位补1,右移24位尾数($96-阶码)次,即可求得尾数绝对值;取补即得到长整数(或整数)。
注:
($96-阶码)为负时为低位补0次数。
3.浮点加减法运算:
减法可对减数改变符号作加法运算;如一个加数为零或两数的阶码值相差大于尾数长度(24位),则可忽略较小的加数,之和取较大的加数;作加法运算前先对阶,小阶对大阶,较小的数尾数右移阶码之差次;尾数作加法运算;结果再浮点规格化,转化成24位尾数最高位刚好为1,化成规定浮点格式。
4.浮点乘法运算:
不需要对准小数点,只要把阶码相加,再减去$7e;尾数相乘;符号相异或;然后对结果进行必要的规格化。
5.浮点数除法运算:
在执行浮点数除法时,应先调整被除数的阶码,使被除数的尾数小于除数的尾数(使商不大于1),然后把阶码相减,再加上$7e;尾数相除;符号相异或。
一般浮点库使用者不必详细了解浮点子程的编写原理,只要求正确使用这些浮点子程,注意入口、出口、使用的寄存器(必要时这些寄存器应加以保护)和使用的内部SRAM地址(应使这些SRAM不作其他常期保留数据的空间和远离堆栈区)。
浮点子程序库(AVR32FP.INC)清单:
INT2FP—16位整数转换成四字节浮点数运算子程
入口:
r17:
r16;出口:
r19:
r18:
r17:
r16
使用的寄存器:
r16,r17,r18,r19,r20,r26。
LONG2FP—32位长整数转换成四字节浮点数运算子程
入口:
r19:
r18:
r17:
r16;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r16,r17,r18,r19,r20,r26。
FP2INT—四字节浮点数转换成16位整数运算子程
入口:
r19:
r18:
r17:
r16;出口:
r19:
r18;
使用的寄存器:
r16,r17,r18,r19,r20,r26。
FP2LONG—四字节浮点数转换成32位长整数运算子程
入口:
r19:
r18:
r17:
r16;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r16,r17,r18,r19,r20,r26。
ADD32F—四字节浮点加法运算子程
入口:
r19:
r18:
r17:
r16+r24:
r23:
r22:
r21;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29;
使用的SRAM:
Y-5,Y-4,Y-3,Y-2,Y-1。
SUB32F—四字节浮点减法运算子程
入口:
r19:
r18:
r17:
r16-r24:
r23:
r22:
r21;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29;
使用的SRAM:
Y-5,Y-4,Y-3,Y-2,Y-1。
DIV32F—四字节浮点除法运算子程
入口:
r19:
r18:
r17:
r16/r24:
r23:
r22:
r21;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29;
使用的SRAM:
Y-1。
MPY32F—四字节浮点乘法运算子程
入口:
r19:
r18:
r17:
r16/r24:
r23:
r22:
r21;出口:
r19:
r18:
r17:
r16;
使用的寄存器:
r13,r14,r15,r16,r17,r18,r19,r20,r21,r22,r23,r24,r25,r26,r28,r29;
使用的SRAM:
Y-1。
INT2FP:
;16位整数转换成四字节浮点数运算子程
CLRR18
SBRCR17,7;R17:
R16为待转换的整数
COMR18
CLRR19;16位整数按数符位扩展成32位长整数
SBRCR18,7;为正,R19,R18清零
COMR19;为负,R19,R18置为$FFFF
LONG2FP:
;32位长整数转换成四字节浮点数运算子程
CLRR20;清符号位R20
ANDR19,R19;先判+/-
BRPLLONG2FP_1;为正,跳至LONG2FP_1
RCALLQUBU;为负,调QUBU子程——取补
COMR20;符号位R20取反
LONG2FP_1:
MOVR26,R16;再判R19:
R18:
R17:
R16是否全零
ORR26,R17
ORR26,R18
ORR26,R19
BRNELONG2FP_2;不为零跳至LONG2FP_2
RJMPJGW0;为零跳至JGW0——结果为零
LONG2FP_2:
LDIR26,$16;令R26=22
RJMPLONG2FP_4
LONG2FP_3:
INCR26
LSRR19
RORR18
RORR17
RORR16
LONG2FP_4:
ANDR19,R19;判高位是否为零
BRNELONG2FP_3;不为零,右移一位,阶码加1
LONG2FP_5:
ANDR18,R18;判次高位是否为零
BRNELONG2FP_7
SUBIR26,$08;为零,阶码减8
MOVR18,R17;数左移8位
MOVR17,R16
LDIR16,$00;低位以$00填充
RJMPLONG2FP_5
LONG2FP_6:
DECR26
ADDR16,R16
ADCR17,R17
ADCR18,R18
LONG2FP_7:
BRPLLONG2FP_6;R18第7为0,再左移一位
MOVR19,R26;阶码减1,直到R18第7位为1
RJMPGGH
FP2INT:
;四字节浮点数转换成16位整数运算子程
LDIR26,$0E;令R26=14
RJMPFP2LONG_1;跳至FP2LONG_1
FP2LONG:
;四字节浮点数转换成32位长整数运算子程
LDIR26,$1E;令R26=30
FP2LONG_1:
RCALLFP2LONG_11;调FP2LONG_11子程
BREQFP2LONG_4;相等,即阶码为0,按0处理
SUBR26,R19;R26(14)-阶码差值
BREQFP2LONG_2;为0,则跳至FP2LONG_2
BRPLFP2LONG_5;为正,则跳至FP2LONG_5——无溢出
FP2LONG_2:
;有溢出
ANDR20,R20;符号为正,
BRMIFP2LONG_3;符号为负,则跳至FP2LONG_3
LDIR16,$FF
LDIR17,$FF
LDIR18,$FF
LDIR19,$7F
RET;正向溢出,结果置为$7FFFFFFF
FP2LONG_3:
LDIR16,$00
LDIR17,$00
LDIR18,$00
LDIR19,$80
RET;负向溢出,结果置为$80000000
FP2LONG_4:
LDIR16,$00
LDIR17,$00
LDIR18,$00
LDIR19,$00
RET;结果为0,置为$00000000
FP2LONG_5:
;无溢出
INCR19;阶码差值+1
BRMIFP2LONG_4;为负,即(阶码<$7E)按零处理
LDIR19,$00;清R19
SUBIR26,$08;R26(14-阶码差值)-8
BRPLFP2LONG_7;为正转FP2LONG_7
SUBIR26,$F8;不够减则加8
MOVR19,R18;左移8位
MOVR18,R17
MOVR17,R16
LDIR16,$7F;低位以$7F填充
RJMPFP2LONG_8;跳至FP2LONG_8
FP2LONG_6:
MOVR16,R17;右移8位
MOVR17,R18
LDIR18,$00;高位以$00填充
SUBIR26,$08;R26-8
FP2LONG_7:
CPIR26,$08;R26值与8相比较
BRCCFP2LONG_6;有借位,跳至FP2LONG_6
FP2LONG_8:
;无借位
ANDR26,R26
BREQFP2LONG_10
FP2LONG_9:
LSRR19;右移一位
RORR18
RORR17
RORR16
DECR26;R26-1,不为0跳至FP2LONG_9
BRNEFP2LONG_9;直到R26为0为止
FP2LONG_10:
;考虑符号位
SBRCR20,7
RJMPQUBU;为负,则跳至QUBU——取补返回
RET;为正,返回
FP2LONG_11:
MOVR20,R19;取浮点数数符存于R20最高位
ANDIR20,$80
ADDR18,R18;将阶码移至R19
ADCR19,R19
SUBIR19,$80;阶码减$80存于R19
SEC
RORR18;恢复尾数最高位1
CPIR19,$80;阶码差值与$80相比较
RET
ADD32F_1:
;存储结果
MOVR20,R25
MOVR19,R24
MOVR18,R23
MOVR17,R22
MOVR16,R21
ADD32F_2:
RJMPGGH;跳至GGH——处理结果
SUB32F:
;四字节浮点减法运算子程
SUBIR24,$80;减数取反,视为浮点加法运算
ADD32F:
;四字节浮点加法运算子程
RCALLYCL;调YCL子程
CPIR24,$80;先判加数是否为0
BREQADD32F_2;为0则和为被加数跳至ADD32F_2
CPIR19,$80;再判被加数是否为0
BREQADD32F_1;为0则和为加数跳至ADD32F_1
ADD32F_3:
MOVR26,R19;转存被加数阶码
SUBR26,R24;R26=被加数阶码减加数阶码
BRVSADD32F_2;溢出,跳至ADD32F_2即加数可忽略
BRMIADD32F_4;为负,跳至ADD32F_4
BRNEADD32F_5;不等,跳至ADD32F_5
CPR16,R21
CPCR17,R22
CPCR18,R23
BRCCADD32F_5
ADD32F_4:
RCALLADD32F_16;调ADD32F_16,被加数和加数相交换
RJMPADD32F_3;跳至ADD32F_3
ADD32F_5:
CPIR26,$18;阶码差值与24相比较
BRCSADD32F_6;C=1,跳至ADD32F_6,即<24
CLRR21;>24加数清0
CLRR22
CLRR23
ADD32F_6:
CPIR26,$08;阶码差值与8相比较
BRCSADD32F_7;C=1,跳至ADD32F_7(直至<8)
MOVR21,R22;加数尾数右移8位
MOVR22,R23;高8位清0
CLRR23
SUBIR26,$08;阶码差值再减8
RJMPADD32F_6;跳至ADD32F_6
ADD32F_7:
ANDR26,R26
BREQADD32F_9;直至R26=0,跳至ADD32F_9
ADD32F_8:
LSRR23;加数尾数右移1位
RORR22
RORR21
DECR26;阶码差值减1
BRNEADD32F_8;不为0跳至ADD32F_8
ADD32F_9:
MOVR26,R20;被加数和加数是否同号
EORR26,R25
BRMIADD32F_10;异号,跳至ADD32F_10
RCALLADD32F_13;同号,调ADD32F_13子程——尾数相加
BRCCADD32F_2;C=0,无溢出,跳至ADD32F_2
RORR18;C=1,溢出,尾数右移1位
RORR17
RORR16
SUBIR19,$FF;阶码加1
BRVCADD32F_2;无溢出,跳至ADD32F_2,处理结果
RJMPJGZD;溢出,跳至JGZD,出结果
ADD32F_10:
RCALLADD32F_14;调ADD32F_14子程——尾数相减
BRNEADD32F_11;不等,跳至ADD32F_11
RJMPJGW0;跳至JGW0,出结果
ADD32F_11:
BRCCADD32F_12;C=0,够减,跳至ADD32F_12
RCALLADD32F_15;C=1,不够减,调ADD32F_15子程——取补
ADD32F_12:
ANDR18,R18;判R18最高位是否位1
BRMIADD32F_2;为1,跳至ADD32F_2,处理结果
ADDR16,R16;为0,尾数左移一位
ADCR17,R17
ADCR18,R18
SUBIR19,$01;阶码减1
BRVCADD32F_12;无溢出,跳至ADD32F_12
RJMPJGZD;溢出,跳至JGZD,出结果
ADD32F_13:
;尾数相加
ADDR16,R21
ADCR17,R22
ADCR18,R23
RET
ADD32F_14:
;尾数相减
SUBR16,R21
SBCR17,R22
SBCR18,R23
RET
ADD32F_15:
;结果取补
COMR17
COMR18
NEGR16
SBCIR17,$FF
SBCIR18,$FF
RET
ADD32F_16:
;两个数相交换
ST-Y,R21
ST-Y,R22
ST-Y,R23
ST-Y,R24
ST-Y,R25
MOVR24,R19
MOVR21,R16
MOVR22,R17
MOVR23,R18
MOVR25,R20
LDR20,Y+
LDR19,Y+
LDR18,Y+
LDR17,Y+
LDR16,Y+
RET
YCL:
MOVR20,R19
LDIR26,$80
ADDR18,R18
ADCR19,R19;将阶码移至R19
EORR19,R26;阶码减$80存于R19
ADDR26,R26
RORR18;恢复尾数最高位1
ANDIR20,$80;取浮点数数符存于R20最高位
MOVR25,R24
LDIR26,$80
ADDR23,R23;将阶码移至R24
ADCR24,R24
EORR24,R26;阶码减$80存于R24
ADDR26,R26
RORR23;恢复尾数最高位1
ANDIR25,$80;取浮点数数符存于R25最高位
CPIR19,$80
RET
GGH:
;规格化
ADDR18,R18;隐含尾数最高位为1
LDIR26,$80;考虑符号位
EORR26,R19;
ADDR20,R20
RORR26;右移R26,R18
RORR18
MOVR19,R26;R26移至R19
RET
DIV32F_1:
ST-Y,R26;转存R26
CLRR13;清R15:
R14:
R13
CLRR14
CLRR15
LDIR26,$18;令R26=$18(24)
DIV32F_2:
CPR16,R21;被除数(余数)与除数两尾数相比
CPCR17,R22
CPCR18,R23
BRCSDIV32F_3;被除数(余数)<除数
SUBR16,R21;余数=被除数-除数
SBCR17,R22
SBCR18,R23
SEC
RJMPDIV32F_4
DIV32F_3:
CLC;清除进位位
DIV32F_4:
ADCR13,R13;商左移一位,并加上进位位
ADCR14,R14
ADCR15,R15
ADDR16,R16;余数左移一位
ADCR17,R17
ADCR18,R18
DECR26;R26-1
BRNEDIV32F_2;循环24次
MOVR16,R13;取出商
MOVR17,R14
MOVR18,R15
LDR26,Y+;恢复R26
RET
DIV32F:
;四字节浮点除法运算子程
ANDR24,R24
BREQDIV32F_7;跳至DIV32F_7,出结果
ANDR19,R19;判被除数是否为0
BREQJGW0;为0,则结果为0
RCALLYCL;调YCL子程
BREQJGW0;跳至JGW0,结果为0
EORR20,R25;取商的符号位存于R20
SEC
SBCR19,R24;取出商的阶码
BRVSJGZD;溢出,跳至JGZD
LSRR23;无溢出
RORR22;将被除数与除数得尾数
RORR21;右移一位,最高位置0
LSRR18
RORR17
RORR16
RCALLDIV32F_1;调DIV32F_1子程,进行运算
ANDR18,R18;判R18最高位是否为0
BRMIDIV32F_5;为