|
M68HC08浮点运算子程序 M68HC08是一种高性能高速8位单片机。它广泛应用于家用电器、仪器仪表和工业控制等场合。 绝大多数单片机应用系统都离不开数值计算,并且有时数的范围可能比较大,计算也比较复杂,这时就需要使用浮点数。为此,下面将介绍适用于M68HC08单片机的一套IEEE单精度浮点运算子程序,它包括浮点四则运算、数制转换、函数运算等子程序。 一. 浮点数格式 浮点数一般采用M×2E的形式来表示,M为,它一般为小数;E为阶码,它为整数。M、E有各种表示方法。对IEEE单精度浮点数,M为符号-数值表示法,可计为S×M:S为符号,正数S=1,负数S=-1。M为24位二进制小数,对规格化浮点数,2>M>=1,故最高位总为1。在存放M时,可省略最高位的1,仅存放23位。E采用移码表示,E=数值+127。例127($7F)表示0,$80表示1,$7E表示-1。存放时的格式如下: 数 符 阶 码(8位) 尾 数 ( 23 位) S
31 30 24 23 22 16 15 8 7 0 该浮点数为4字节,可表示的最大值为1038,最小值(绝对值)为 10-38。它的有效数字约为七位十进制数。全0表示零,第一字节为FF表示溢出。 本套浮点运算子程序中,除了M68HC08的A、H、X寄存器外,不使用其他固定RAM单元。它使用堆栈来传递参数和运算结果,中间运算单元也使用堆栈来实现,以方便子程序调用。堆栈中传递的浮点数,低位地址存放浮点数的高位字节。 二. 浮点四则运算子程序 1. 加法子程序 FADD ①功能:X+Y-> Z 入口:X、Y在堆栈中,Y在高位地址,X在低位地址,格式如下图(E表示阶码(高位字节),H表示高位尾数,M表示中位尾数,L表示低位尾数)。 SP SP + 1XE SP + 2XH SP + 3XM SP + 4XL SP + 5YE SP + 6YH SP + 7YM SP + 8YL
出口:Z在堆栈中,格式如下图。 SP SP + 1ZE SP + 2ZH SP + 3ZM SP + 4ZL
FADD 需使用12字节堆栈区(含8字节的X、Y,2字节调用指令的返回地址)。 执行时间约20-80μs。 ②算法: 1) 对阶:右移阶小的数的尾数,使它的阶码等于大阶。 2) 执行定点数(尾数)加(减)法运算。 3) 结果规格化。 ③程序: *************************************************** * FADD: Addition X + Y -> Z * * Entry: X,Y in Stack * * Exit: Z in Stack * *************************************************** FADD: AIS #-2 LDA 9,SP LSL 10,SP ROLA SEC ROR 10,SP ;Y=9,10,11 STA 2,SP ;Ym LDA 5,SP LSL 6,SP ROLA SEC ROR 6,SP ;X=5,6,7 STA 1,SP ;Xm CMP #0 BEQ FAD5X SUB 2,SP BEQ FAD1 BCC FAD4 NEGA CMP #24 BHS FAD5X LDX 2,SP STX 1,SP FAD0: LSR 6,SP ROR 7,SP ROR 8,SP DBNZA FAD0 FAD1: LDA 5,SP EOR 9,SP BMI FAD6 LDA 8,SP ADD 12,SP STA 12,SP LDA 7,SP ADC 11,SP STA 11,SP LDA 6,SP ADC 10,SP BCC FAD2 INC 1,SP ;Over Flow RORA TAX ROR 11,SP ROR 12,SP BCC FAD2 INC 12,SP BNE FAD2 LDA 11,SP ADC #0 STA 11,SP TXA ADC #0 FAD2: LSLA STA 10,SP LSL 5,SP; X Sign LDA 1,SP RORA STA 9,SP ROR 10,SP FAD3: LDA 4,SP ;Move PC(in Stack) STA 8,SP LDA 3,SP STA 7,SP AIS #6 RTS FAD5X: BRA FAD5 FAD4: TST 2,SP BEQ FAD9 CMP #24 BHS FAD9 FADA: LSR 10,SP ROR 11,SP ROR 12,SP DBNZA FADA BRA FAD1 FAD5: LSL 10,SP LSR 2,SP ROR 10,SP FAD3X: BRA FAD3 FAD6: LDA 8,SP SUB 12,SP STA 12,SP LDA 7,SP SBC 11,SP STA 11,SP LDA 6,SP SBC 10,SP BCC FAD8 NEG 12,SP ;UnderFlow STA 10,SP CLRA SBC 11,SP STA 11,SP CLRA SBC 10,SP COM 5,SP ;/X Sign FAD8: BIT #$80 BNE FAD2 LSL 12,SP ROL 11,SP ROLA TSTA BNE FADC TST 11,SP BNE FADC TST 12,SP BEQ FADE FADC: DEC 1,SP BNE FAD8 FADE: CLR 9,SP CLR 10,SP CLR 11,SP CLR 12,SP BRA FAD3X FAD9: LDA 6,SP LSLA LSL 5,SP; X Sign ROR 1,SP RORA STA 10,SP LDA 1,SP STA 9,SP LDA 7,SP STA 11,SP LDA 8,SP STA 12,SP BRA FAD3X 2. 减法子程序: FSUB ①功能:X-Y-> Z 参数传递方法、使用的堆栈和算法、执行时间同FADD。 ②程序: *************************************************** * FSUB: Subtraction X - Y -> Z * * Entry: X,Y in Stack * * Exit: Z in Stack * *************************************************** FSB5: LSL 10,SP LSR 2,SP ROR 10,SP FSB3X: JMP FSB3 FSUB: AIS #-2 LDA 9,SP LSL 10,SP ROLA SEC ROR 10,SP ;Y=9,10,11 STA 2,SP ;Ym LDA 5,SP LSL 6,SP ROLA SEC ROR 6,SP ;X=5,6,7 STA 1,SP ;Xm CMP #0 BEQ FSB5 SUB 2,SP BEQ FSB1 BCC FSB4 NEGA CMP #24 BHS FSB5 LDX 2,SP STX 1,SP FSB0: LSR 6,SP ROR 7,SP ROR 8,SP DBNZA FSB0 FSB1: LDA 5,SP EOR 9,SP BPL FSB6 LDA 8,SP ADD 12,SP STA 12,SP LDA 7,SP ADC 11,SP STA 11,SP LDA 6,SP ADC 10,SP BCC FSB2 INC 1,SP ;Over Flow RORA TAX ROR 11,SP ROR 12,SP BCC FSB2 INC 12,SP BNE FSB2 LDA 11,SP ADC #0 STA 11,SP TXA ADC #0 FSB2: LSLA STA 10,SP LSL 5,SP; X Sign LDA 1,SP RORA STA 9,SP ROR 10,SP FSB3: LDA 4,SP ;Move PC(in Stack) STA 8,SP LDA 3,SP STA 7,SP AIS #6 RTS FSB4: TST 2,SP BEQ FSB9 CMP #24 BHS FSB9 FSBA: LSR 10,SP ROR 11,SP ROR 12,SP DBNZA FSBA BRA FSB1 FSB6: LDA 8,SP SUB 12,SP STA 12,SP LDA 7,SP SBC 11,SP STA 11,SP LDA 6,SP SBC 10,SP BCC FSB8 NEG 12,SP ;UnderFlow TAX LDA 11,SP SBC #0 STA 11,SP TXA SBC #0 COM 5,SP ;/X Sign FSB8: BIT #$80 BNE FSB2 LSL 12,SP ROL 11,SP ROLA TSTA BNE FSBC TST 11,SP BNE FSBC TST 12,SP BEQ FSBD FSBC: DEC 1,SP BNE FSB8 FSBD: CLR 9,SP CLR 10,SP CLR 11,SP CLR 12,SP FSB3Y: JMP FSB3 FSB9: LDA 6,SP LSLA LSL 5,SP; X Sign ROR 1,SP RORA STA 10,SP LDA 1,SP STA 9,SP LDA 7,SP STA 11,SP LDA 8,SP STA 12,SP BRA FSB3Y 3. 乘法子程序:FMUL ①功能:X×Y-> Z 参数传递方法同FADD。它需使用12字节堆栈区(含8字节的X、Y,2字节调用指令的返回地址)。 执行时间约50μs。 ②算法: 1) 执行尾数乘法,使用M68HC08的MUL指令实现。 2) 阶码相加。 3) 结果规格化。 ③程序: *************************************************** * FMUL: Multiply X * Y -> Z * * Entry: X,Y in Stack * * Exit: Z in Stack * *************************************************** FML0: CLR 8,SP CLR 9,SP CLR 10,SP CLR 11,SP JMP FML1 FMUL: AIS #-1 LDA 8,SP EOR 4,SP TAX LDA 8,SP LSL 9,SP ROLA BEQ FML0 SEC STA 1,SP ROR 9,SP LDA 4,SP LSL 5,SP ROLA BEQ FML0 SEC ROR 5,SP ADD 1,SP SUB #$7E ;-126 STA 8,SP STX 1,SP ;Sign LDA 11,SP LDX 6,SP MUL STX 4,SP LDA 11,SP LDX 5,SP MUL ADD 4,SP STA 4,SP TXA ADC #0 STA 11,SP LDA 10,SP LDX 7,SP MUL TXA ADD 4,SP STA 4,SP CLRA ADC 11,SP STA 11,SP LDA 10,SP LDX 6,SP MUL ADD 4,SP STA 4,SP TXA ADC 11,SP STA 11,SP CLRA ADC #0 PSHA LDA 10,SP LDX 8,SP MUL ADD 5,SP STA 5,SP TXA ADC 12,SP STA 12,SP PULA ADC #0 STA 7,SP LDA 10,SP LDX 5,SP MUL ADD 11,SP STA 11,SP TXA ADC 7,SP STA 10,SP CLRA ADC #0 STA 7,SP LDA 9,SP LDX 6,SP MUL ADD 11,SP STA 11,SP TXA ADC 10,SP STA 10,SP CLRA ADC 7,SP STA 4,SP LDA 9,SP LDX 5,SP MUL ADD 10,SP STA 10,SP TXA ADC 4,SP FML2: BIT #$80 BNE FML3 LSL 11,SP ROL 10,SP ROLA DEC 8,SP BNE FML2 FML3: LSLA LSL 1,SP ;Sign ROR 8,SP RORA STA 9,SP FML1: LDA 2,SP STA 6,SP LDA 3,SP STA 7,SP AIS #5 RTS 4. 除法子程序:FDIV ①功能:X÷Y-> Z 参数传递方法同FADD。它需使用13字节堆栈区(含8字节的X、Y,2字节调用指令的返回地址)。 执行时间约230μs。 ②算法: 1) 判断除数是否等于零,等于则出错(C=1)。 2) 比较被除数与除数的尾数,如大于等于则左移被除数尾数(阶加1)。 3) 阶码相减。 4) 尾数相除(采用比较除法)。 ③程序: *************************************************** * FDIV: Division X / Y -> Z * * Entry: X,Y in Stack * * Exit: Z in Stack * *************************************************** FDV1: CLR 13,SP CLR 12,SP CLR 11,SP CLR 10,SP CLC FDV8: JMP FDV7 FDV0: LDA #$FF STA 13,SP STA 12,SP STA 11,SP STA 10,SP SEC BRA FDV8 FDIV: AIS #-3 LDA 10,SP EOR 6,SP TAX LDA 10,SP LSL 11,SP ROLA BEQ FDV1 SEC ROR 11,SP STA 1,SP LDA 6,SP LSL 7,SP ROLA BEQ FDV0 SEC ROR 7,SP SUB 1,SP ADD #$7E ;+126 STA 10,SP STX 6,SP ;Sign CLR 3,SP CLR 2,SP CLR 1,SP LDA 9,SP SUB 13,SP LDA 8,SP SBC 12,SP LDA 7,SP SBC 11,SP BCS FDV2 LSR 7,SP ROR 8,SP ROR 9,SP ROR 3,SP INC 10,SP FDV2: LDX #24 FDV3: LSL 1,SP ROL 2,SP ROL 3,SP ROL 9,SP ROL 8,SP ROL 7,SP BCS FDV4 LDA 9,SP SUB 13,SP LDA 8,SP SBC 12,SP LDA 7,SP SBC 11,SP BCS FDV5 FDV4: LDA 9,SP SUB 13,SP STA 9,SP LDA 8,SP SBC 12,SP STA 8,SP LDA 7,SP SBC 11,SP STA 7,SP INC 1,SP FDV5: DBNZX FDV3 LDA 1,SP STA 13,SP LDA 2,SP STA 12,SP LDA 3,SP LSLA LSL 6,SP ;Sign ROR 10,SP RORA STA 11,SP FDV6: CLC FDV7: AIS #3 PULH PULX AIS #4 JMP ,X 三. 浮点数制转换子程序 1. 长整数至浮点数转换子程序:INTF ①功能:长整数(4字节)转换成浮点数X。 入口:长整数在堆栈中,高位地址放高位字节。 出口:X在堆栈中。 它需使用8字节堆栈区(含4字节的 长整数,2字节调用指令的返回地址)。 执行时间约20-140μs(与数据有关)。 ②算法: 1) 置阶码为24。 2) 对负数则取补长整数,并置符号位。 3) 执行规格化操作。 ③程序: *************************************************** * INTF: Long Integer to FP Subroutine * * Entry: Fixed Number (2's Complement) * * in Stack(4 Bytes) * * Exit: Floating Point Number in Stack * *************************************************** INTF: LDA #$96 PSHA LDA 4,SP AND #$80 PSHA ;Sign BEQ INTF1 NEG 8,SP CLRA SBC 7,SP STA 7,SP CLRA SBC 6,SP STA 6,SP CLRA SBC 5,SP STA 5,SP INTF1: LDA 5,SP ORA 6,SP ORA 7,SP ORA 8,SP BEQ INTF4 LDA 5,SP INTF2: BIT #$80 BNE INTF3 LSL 8,SP ROL 7,SP ROL 6,SP ROLA DEC 2,SP BRA INTF2 INTF3: LSLA LSL 1,SP ROR 2,SP RORA LDX 7,SP STX 8,SP LDX 6,SP STX 7,SP STA 6,SP LDA 2,SP STA 5,SP INTF4: AIS #2 RTS 2. 无符号长整数至浮点数转换子程序:UINF ①功能:无符号长整数(4字节)转换成浮点数X。 参数传递方法、使用的堆栈和执行时间同INTF。 ②程序: *************************************************** * UINF: Unsigned Long Integer to FP * * Entry: Fixed Number in Stack(4 Bytes) * * Exit: Floating Point Number in Stack * *************************************************** UINF: LDA #$96 PSHA UINF1: LDA 7,SP ORA 6,SP ORA 5,SP ORA 4,SP BEQ UINF4 LDA 4,SP UINF2: BIT #$80 BNE UINF3 LSL 7,SP ROL 6,SP ROL 5,SP ROLA DEC 1,SP BRA UINF2 UINF3: LSLA CLC ROR 1,SP RORA LDX 6,SP STX 7,SP LDX 5,SP STX 6,SP STA 5,SP LDA 1,SP STA 4,SP UINF4: AIS #1 RTS 3. 浮点数至长整数转换子程序:FTIN ①功能:浮点数X转换成四字节补码长整数Y。 入口:X在堆栈中。 出口:长整数Y在堆栈中,高位地址放高位字节。 它需使用6字节堆栈区(含4字节浮点数,2字节调用指令的返回地址)。 执行时间约20-100μs(与数据有关)。 ②算法: 1) 判断阶码是否大于31,大于则为溢出(结果=$7FFFFFFF)。 2) 尾数扩展为四字节。 3) 阶码小于23,则右移尾数,阶码加1,至阶码等于23。 阶码大于23,则左移尾数,阶码减1,至阶码等于23。 4) 按符号位取补尾数。 ③程序: *************************************************** * FTIN: FP to Long Integer Subroutine * * Entry: FP in Stack * * Exit: Result in Stack(2's Complement) * * (4 Bytes) ($7FFFFFFF Overflow) * *************************************************** FTIN: LDX 3,SP LDA 4,SP LSLA ROLX SEC RORA STA 4,SP CPX #33+126 BPL FTIN1 CLRA CPX #127 BMI FTIN0 FTIN2: CPX #24+126 BEQ FTIN4 BPL FTIN3 INCX LSR 4,SP ROR 5,SP ROR 6,SP BRA FTIN2 FTIN3: DECX LSL 6,SP ROL 5,SP ROL 4,SP ROLA BRA FTIN2 FTIN1: LDA #$7F STA 3,SP LDA #$FF STA 4,SP STA 5,SP STA 6,SP RTS FTIN0: STA 3,SP STA 4,SP STA 5,SP STA 6,SP RTS FTIN4: TST 3,SP BPL FTIN5 STA 3,SP NEG 6,SP CLRA SBC 5,SP STA 5,SP CLRA SBC 4,SP STA 4,SP CLRA SBC 3,SP STA 3,SP RTS FTIN5: STA 3,SP RTS 4. 浮点数取整子程序:FINT ①功能:浮点数X取整。 入口:X在堆栈中。 出口:X在堆栈中,如X>224 则X不变。 它需使用6字节堆栈区(含4字节浮点数,2字节调用指令的返回地址)。 执行时间约50-120μs(与数据有关)。 ②算法: 1) 判断阶码是否大于23,大于则不处理,直接返回。 2) 右移尾数,阶码加1,至阶码等于23。 3) 结果规格化。 ③程序: *************************************************** * FINT: Get Integer Subroutine * * Entry: FP in Stack * * Exit: Integer(FP Number) in Stack * *************************************************** FINT: LDX 3,SP LDA 4,SP LSLA ROLX CPX #24+126 BPL FINT1 LDA 4,SP ORA #$80 CPX #127 BMI FINT0 FINT2: CPX #24+126 BEQ FINT3 INCX LSRA ROR 5,SP ROR 6,SP BRA FINT2 FINT0: CLRX STX 3,SP STX 4,SP STX 5,SP STX 6,SP FINT1: RTS FINT3: BIT #$80 BNE FINT4 LSL 6,SP ROL 5,SP ROLA DECX BRA FINT3 FINT4: LSLA LSL 3,SP RORX RORA STA 4,SP STX 3,SP RTS 5. 浮点数二翻十子程序:FBTD ①功能:把二进制浮点数X转换成十进制浮点数Y。 入口:X在堆栈中。 出口:十进制浮点数Y在堆栈中,其中十进制浮点数的阶码采用二进制补码格式,放于高位地址,下面依次为七位单字节BCD码尾数。尾数为小数,小数点在第一位BCD码后,即尾数为大于等于1小于10的十进制数。 它需使用14字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约150-500μs(与数据有关)。 ②算法: 1) 置十进制阶码为0。 2) 如浮点数小于1,则乘以十,并把十进制阶码加1。 3) 右移浮点数尾数,阶码加1,至阶码等于4。 4) 把浮点数尾数转换成十进制小数(单字节BCD码格式)。 ③例: 1) 设X=1.234567,转换后,堆栈中从SP+1开始依次为07,06,05,04,03,02,01,00。 2) 设X=-0.01234567,转换后,堆栈中从SP+1开始依次为07,06,05,04,03,02,01,FE。 ④程序: *************************************************** * FBTD: Floating Point Binary Number to * * Decimal Convert Subroutine * * Entry: Binary Number X in Stack * * Exit: Decimal Number(BCD) in Stack (SP)+7~1 * * Exponent in (SP)+8 * * For Example: * * When X = 123.4567, Stack will be as * * 02, 01,02,03,04,05,06,07 * *************************************************** FBTD: LDA 3,SP BNE FBTD1 PULH ;Zero PULX AIS #-4 STA 1,SP STA 2,SP STA 3,SP STA 4,SP JMP ,X FBTD1: LDX 6,SP PSHX LDX 6,SP PSHX LDX 6,SP PSHX PSHA TAX AND #$80 STA 10,SP ;BCD Sign FBTD2: LDA 2,SP LSLA ROLX CPX #$82 BEQ FBTD6 BHI FBTD7 FBTD3: CPX #$7F BEQ FBTD8 BCS FBTD9 FBTD4: STX 1,SP LDA #$83 SUB 1,SP TAX LDA 2,SP ORA #$80 FBTD41: LSRA ROR 3,SP ROR 4,SP DBNZX FBTD41 STA 2,SP LDX 6,SP ; PCL PSHX LDX 6,SP ; PCH PSHX LDA #6 ; Count PSHA LDX #5 CLRA SEC FBTD42: ROL 7,SP ROL 6,SP ROL 5,SP ROLA DBNZX FBTD42 TSX AIX #10 STA 1,X BRA FBTD5 FBTD6: LDA 2,SP ORA #$80 SUB #$A0 BLO FBTD4 FBTD7: LDA #$CE ;0.1 PSHA LDA #$CC PSHA PSHA LDA #$3D PSHA JSR FMUL INC 10,SP LDX 1,SP JMP FBTD2 FBTD8: LDA 2,SP BNE FBTD4 FBTD9: CLRA PSHA PSHA LDA #$20 PSHA LDA #$41 PSHA JSR FMUL DEC 10,SP LDX 1,SP JMP FBTD2 FBTD5: LDA 7,SP STA 4,SP PSHX LDA 5,SP LDX #10 MUL STA 5,SP LDA 7,SP STX 7,SP LDX #10 MUL ADD 7,SP STA 7,SP TXA ADC #0 LDX 6,SP STA 6,SP LDA #10 MUL ADD 6,SP STA 6,SP TXA ADC #0 PULX STA ,X AIX #-1 DEC 1,SP BNE FBTD5 AIS #1 PULH PULX AIS #2 JMP ,X ;Return 6. 浮点数十翻二子程序:FDTB ①功能:把H、X指向的ASCII码字符串表示的十进制数转换成二进制浮点数X。 入口:H、X指向的ASCII码字符串首地址。 出口:二进制浮点数X在堆栈中。 它需使用18字节堆栈区(含2字节调用指令的返回地址)。 执行时间约400-1000μs(与数据有关)。 ②十进制数允许为以下形式: 123.4567;-1.23456; 0.00123456等。 它必须以回车或’,’结尾,否则出口时C=1。 ③算法: 1) 清零二进制浮点数、小数点位置计数。 2) 按+、-号置符号位。 3) 执行十翻二,并置小数点位置计数值。 4) 按小数点位置计数循环执行除以十的运算。 5) 置浮点数符号,存放结果。 ④程序: *************************************************** * FDTB: Decimal Number(ASCII String) to * * Binary Floating Point Convert Subroutine * * Entry: Decimal Number ASCII String * * (End With 'CR' or ',') in RAM * * Location Pointed by Register HX * * Exit: Binary Floating Point Number in Stack * * For Example: The String Can Be * * 123.45; -1.2345; 0.0012345; +12345678 etc. * *************************************************** FDTB: CLRA PSHA ;FLAG PSHA ;E Counter AIS #-2 PSHA ;Initial Result(Y) PSHA PSHA PSHA LDA ,X AIX #1 CMP #$2B ; + BEQ FDTB1 CMP #$2D ; - BNE FDTB2 LDA 8,SP ORA #$80 ;Negative Flag STA 8,SP FDTB1: LDA ,X AIX #1 FDTB2: CMP #$30 BLO FDTB6 CMP #$3A BHS FDTB6 FDTB3: SUB #$30 NSA STA 5,SP ;Save a STX 6,SP ;Save X LDA #$01 PSHA ;10 CLRA PSHA LDA #$20 PSHA LDA #$41 PSHA JSR FMUL ;Y * 10 -> Y CLRA PSHA PSHA CLRX LDA 7,SP BEQ FDTB31 LDX #$82 FDTB30: TSTA BMI FDTB31 LSLA DECX BRA FDTB30 FDTB31: LSLA LSRX RORA PSHA PSHX JSR FADD ;Y + a -> Y LDA 8,SP LSRA BCC FDTB4 INC 7,SP ;Meet Digital Point FDTB4: LDX 6,SP FDTB5: LDA ,X AIX #1 CMP #$30 BLO FDTB6 CMP #$3A BLO FDTB3 FDTB6: PSHA LDA 8,SP LSRA PULA BCS FDTB7 CMP #$2E; . BNE FDTB7 INC 8,SP BRA FDTB5 FDTB7: CMP #$0D BNE FDTBA FDTBB: LDA 8,SP LSRA BCC FDTB9 FDTB8: LDA #$CE ; 0.1 PSHA LDA #$CC PSHA PSHA LDA #$3D PSHA JSR FMUL DBNZ 7,SP,FDTB8 FDTB9: LDX 10,SP LDA 9,SP PSHA PULH LDA 1,SP LSLA LSL 8,SP RORA STA 7,SP LDA 3,SP STA 9,SP LDA 2,SP STA 8,SP LDA 4,SP STA 10,SP AIS #6 JMP ,X ;CY=1 Error FDTBA: CMP #$2C ; , BEQ FDTBB LDA 8,SP ORA #$40 ;Error Flag STA 8,SP BRA FDTBB 四. 浮点函数子程序 1. 浮点多项式子程序:FPLN ①功能:计算Y=Pn(X) = An Xn + An-1 Xn-1 +......+ A1 X + A0 入口:X在堆栈中,An ~ A0在调用指令后,以$FF结束,格式如下: JSR FPLN FCB AnE, AnH, AnM, AnL FCB An-1E,An-1H,An-1M,An-1L ...... FCB A0E, A0H, A0M, A0L FCB $FF 后继程序 出口:Y在堆栈中。 它需使用18字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间取决于X的次方数。 ②算法: 它采用循环方法来计算Pn(X),公式如下: Y= Pn(X) = (......(An×X + An-1)×X + ......+A1)×X + A0 ③程序: *************************************************** * FPLN: Polynomial Subroutine * * Y = An*X^N + ...+ A1*X + A0 * * Entry: An,...,A1,A0 in ROM Location after * * JSR FPLN instruction, Ended with $FF * * X in Stack * * Exit: Y in Stack * *************************************************** FPLN: TSX LDA ,X PSHA LDX 1,X PULH ;(HX)=An's Address LDA 3,X ;Y=An PSHA LDA 2,X PSHA LDA 1,X PSHA LDA ,X PSHA AIX #4 STX 5,SP PSHH PULA STA 6,SP FPLN1: LDA 10,SP ;X PSHA LDA 10,SP PSHA LDA 10,SP PSHA LDA 10,SP PSHA JSR FMUL ;Y*X->Y LDA 6,SP PSHA PULH LDX 5,SP LDA 3,X ;Ai PSHA LDA 2,X PSHA LDA 1,X PSHA LDA ,X PSHA JSR FADD ;Y+Ai->Y LDA 6,SP PSHA PULH LDX 5,SP AIX #4 STX 5,SP PSHH PULA STA 6,SP LDA ,X CMP #$FF BNE FPLN1 FPLNE: LDA 1,SP STA 7,SP LDA 2,SP STA 8,SP LDA 3,SP STA 9,SP LDA 4,SP STA 10,SP AIX #1 AIS #6 JMP ,X ;Return 2. 浮点开平方子程序:FSQR ①功能:计算 Y = SQR(X)。 入口:X在堆栈中。 出口:C=1,出错(负数开平方);C=0,正常,Y在堆栈中。 它需使用23字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约1000-2000μs(与数据有关)。 ②算法: 采用牛顿迭代法,对Y=SQR(X),如下计算: 1) X-> Z。 2) ( Z + X/Z ) / 2 -> Y。 3) 如|Z-Y|< 0.000001退出;否则Y -> Z,转2)。 4) 把浮点数尾数转换成十进制小数(单字节BCD码格式)。 ③例: 入口时 X=2 ($40,$00,$00,$00),出口时,Y = 1.414213538 ($3F,$B5,$04,$F3)。 误差:0.000000024. ④程序: *************************************************** * FSQR: Square Root Subroutine Y = SQR(X) * * Entry: X in Stack * * Exit: CY = 1, Error; = 0 Normal * * Y in Stack * *************************************************** FSQR: LDA 3,SP ;SQR(X)->Y BPL FSQR1 SEC RTS FSQR1: BNE FSQR2 CLC RTS FSQR2: AIS #-4 ;X->Yi PSHA LDA 10,SP PSHA LDA 10,SP PSHA LDA 10,SP PSHA FSQR3: LDA 1,SP ;Yi->Y STA 5,SP LDA 2,SP STA 6,SP LDA 3,SP STA 7,SP LDA 4,SP STA 8,SP LDA 14,SP ;X PSHA LDA 14,SP PSHA LDA 14,SP PSHA LDA 14,SP PSHA JSR FDIV ;X/Yi LDA 8,SP ;Yi PSHA LDA 8,SP PSHA LDA 8,SP PSHA LDA 8,SP PSHA JSR FADD ;+Yi->Y LDA 1,SP LSL 2,SP ROLA DECA ;Y/2->Yi+1 PSHA RORA ROR 3,SP STA 2,SP LDA 6,SP LDX 7,SP LSLX ROLA CMP 1,SP BNE FSQR4 PULX LDA 4,SP SUB 8,SP PSHA LDA 4,SP SBC 8,SP BNE FSQR4 LDA 3,SP SBC 7,SP BNE FSQR4 PULA AND #$F0 BNE FSQR3 LDA 1,SP STA 11,SP LDA 2,SP STA 12,SP LDA 3,SP STA 13,SP LDA 4,SP STA 14,SP AIS #8 CLC RTS FSQR4: PULA JMP FSQR3 3. 指数函数子程序:FEXP ①功能:计算 Y = EXP(X)=EX。 入口:X在堆栈中。 出口:Y在堆栈中。 它需使用25字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约770μs。 ②算法: 采用指数变换法和切比雪夫插值法计算。先计算X×( 1/ln2),取它的整数部分为m,小数部分为t,再用下式计算2t: Z = 2t = 0.0000159268622*t7 + 0.00075674366*t6 + 0.00133248629*t5 + 0.0096164148*t4 + 0.05550444*t3 + 0.240220823*t2 + 0.69314744*t + 0.99999999 最后计算 EX=2log2EX = 2 X*(1/ln2) = 2 m+t = 2m * 2t = 2m * Z = 2 m * 2Z阶*Z尾 = 2 m+Z阶 * Z尾 = Y ③例: 入口时 X=1.5 ($3F,$C0,$00,$00),出口时,Y = 4.481688499 ($40,$8F,$69,$FE)。 误差:-0.00000057. ④程序: *************************************************** * FEXP: Exponent Function Subroutine * * Y = EXP(X) ( E^X ) * * Entry: X in Stack * * Exit: Y in Stack * *************************************************** FEXP: LDA 6,SP PSHA ;X->X LDA 6,SP PSHA LDA 6,SP PSHA LDA 6,SP PSHA LDA #$3F ;1/ln2=1.442695041 PSHA LDA #$B8 PSHA LDA #$AA PSHA LDA #$3B PSHA JSR FMUL ;X*1/ln2->Y LDA 1,SP PSHA AIS #-3 PSHA LDA 7,SP STA 6,SP STA 2,SP LDA 8,SP STA 7,SP STA 3,SP LDX 9,SP ; b7=Sign STX 8,SP STX 4,SP LSLA ROLX CPX #$7F BHS FEXP0 CLR 9,SP AIS #4 BRA FEXP4 FEXP0: CPX #$86 BHS FEXP5 SEC RORA FEXP1: LSRA INCX CPX #$86 BNE FEXP1 PSHA TST 10,SP BPL FEXPX NEGA FEXPX: STA 10,SP ;m PULA FEXP2: BIT #$80 BNE FEXP3 LSLA DECX BRA FEXP2 FEXP3: CLR 5,SP CLR 6,SP LSLA STA 7,SP LDA 4,SP LSLA RORX ROR 7,SP STX 8,SP ;M JSR FSUB ;Y-M->Y FEXP4: JSR FPLN FCB $37,$85,$9A,$AD ;0.0000159268622 FCB $39,$24,$5B,$8F ;0.000156743669 FCB $3A,$AE,$A6,$D2 ;0.00133248629 FCB $3C,$1D,$8E,$2B ;0.0096164148 FCB $3D,$63,$58,$A0 ;0.05550444 FCB $3E,$75,$FE,$06 ;0.240226833 FCB $3F,$31,$72,$17 ;0.693147144 FCB $3F,$7F,$FF,$FF ;0.99999999 FCB $FF LDA 4,SP LDX 3,SP LSLX ROLA ADD 5,SP LSRA STA 11,SP RORX STX 10,SP LDA 2,SP STA 9,SP LDA 1,SP STA 8,SP AIS #5 RTS FEXP5: AIS #9 LDA 6,SP BPL FEXP6 CLR 6,SP ; 0 -> Y CLR 5,SP CLR 4,SP CLR 3,SP RTS FEXP6: LDA #$FF ; Over Flow STA 6,SP STA 5,SP STA 4,SP STA 3,SP RTS 4. 自然对数子程序:FLNX ①功能:计算 Y = ln X。 入口:X在堆栈中。 出口:Y在堆栈中。 它需使用18字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约700μs。 ②算法: 采用指数变换法和切比雪夫插值法计算。 设X= 2m * V,m为X的阶码,V为尾数。对规格化浮点数X有0.5≤V<1。取t=2V+1(0V<1),计算: Z = 2t = 0.0000159268622*t7 + 0.00075674366*t6 + 0.00133248629*t5 + 0.0096164148*t4 + 0.05550444*t3 + 0.240220823*t2 + 0.69314744*t + 0.99999999 最后计算 EX=2log2EX = 2 X*(1/ln2) = 2 m+t = 2m * 2t = 2m * Z = 2 m * 2Z阶*Z尾 = 2 m+Z阶 * Z尾 = Y ③例: 入口时 X=1.5 ($3F,$C0,$00,$00),出口时,Y = 0.405465096 ($3E,$CF,$99,$1F)。 误差:-0.00000011. ④程序: *************************************************** * FLNX: Nature Log Function Subroutine * * Y = LN(X) * * Entry: X in Stack * * Exit: Y in Stack * * CY=0 Normal; =1 Error * *************************************************** FLNX: LDX 6,SP BPL FLNX1 FLNX0: SEC RTS FLNX1: BEQ FLNX0 LDA 5,SP LSLA ROLX STX 6,SP ; m LDA #$3F PSHA AIS #-3 LDA 7,SP LSLA STA 1,SP LDA 8,SP ROLA STA 2,SP LDA 9,SP ROLA BMI FLNXX STA 3,SP ORA 2,SP ORA 1,SP BNE FLNXY CLR 4,SP BRA FLNXZ FLNXX: AND #$7F STA 3,SP FLNXY: JSR FPLN FCB $BB,$C4,$D3,$0E ; -0.006006605022864279 FCB $3D,$0C,$59,$09 ; 0.03426459984137959 FCB $BD,$BD,$02,$C2 ; -0.09229041719019296 FCB $3E,$28,$F5,$45 ; 0.1649981296672941 FCB $BE,$75,$2E,$05 ; -0.2394333706639132 FCB $3E,$A9,$B3,$60 ; 0.3314466522210199 FCB $BE,$FF,$E9,$20 ; -0.4998254986403609 FCB $3F,$7F,$FF,$95 ; 0.9999936302583357 FCB $33,$27,$F8,$DD; 3.910905799209274D-8 FCB $FF FLNXZ: LDA 10,SP SUB #$7F STA 10,SP BEQ FLNX6 BPL FLNX2 NEGA FLNX2: PSHA LDX #$18 MUL AIS #-3 STA 1,SP STX 2,SP LDA 4,SP LDX #$72 MUL ADD 2,SP STA 2,SP TXA ADC #0 STA 3,SP LDA 4,SP LDX #$B1 MUL ADD 3,SP STA 3,SP TXA LDX #$86 ADC #0 FLNX3: BMI FLNX5 FLNX4: DECX LSL 1,SP ROL 2,SP ROL 3,SP ROLA BPL FLNX4 FLNX5: LSLA LSL 14,SP ;Sign RORX RORA STX 4,SP LDX 3,SP STA 3,SP LDA 2,SP STA 1,SP STX 2,SP JSR FADD FLNX6: LDA 1,SP STA 7,SP LDA 2,SP STA 8,SP LDA 3,SP STA 9,SP LDA 4,SP STA 10,SP AIS #4 RTS 5. 三角函数子程序: 正弦函数子程序FSIN,余弦函数子程序FCOS,正切函数子程序FTAN。 ①功能:计算 Y = sin X,Y=cosX,Y=tgX。 入口:X(弧度值)在堆栈中。 出口:Y在堆栈中。 它需使用25、25、35字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约600、650、1500μs。 ②算法: 采用变换法和切比雪夫插值法计算。对Y=sinX,先通过正弦函数的周期性把自变量变为0~π/2之间的值,再计算 sinX = -0.0001379132*X7-0.0002024423*X6+0.008632133*X5-0.000232082*X4-0.166571*X3-0.00001911347*X2+1.0000014*X-0.0000000177308 然后按自变量的范围置sinX的符号。 对cosX,采用cosX=sin(π/2-X)来计算。 对tgX,采用tgX=sinX/cosX来计算。 ③例: 入口时 X=1.5 ($3F,$C0,$00,$00),出口时,Y = sinX= 0.997495055 ($3F,$7F,$5B,$D6)。 误差:0.000000068. ④程序: *************************************************** * FSIN: Sine Function Subroutine Y = SIN(X) * * FCOS: Cosine Function Subroutine Y = COS(X) * * FTAN: Tangent Function Subroutine Y=TAN(X) * * Entry: X in Stack * * Exit: Y in Stack * *************************************************** FSIN: LDA 6,SP EOR #$80 PSHA ;Sign LDA #$C0 PSHA LDA #$49 PSHA LDA #$0F ;-3.1415926 PSHA LDA #$DB PSHA LDA 11,SP AND #$7F PSHA LDA 11,SP PSHA LDA 11,SP PSHA LDA 11,SP PSHA FSIN1: LDA 9,SP ;/Sign -> Sign EOR #$80 STA 9,SP JSR FADD TST 4,SP BMI FSIN2 LDA #$C0 PSHA LDA #$49 PSHA LDA #$0F ;-3.1415926 PSHA LDA #$DB PSHA BRA FSIN1 FSIN2: LDA #$3F PSHA LDA #$C9 PSHA LDA #$0F ;3.1415926/2 PSHA LDA #$DB PSHA JSR FADD LDA #$3F PSHA LDA #$C9 PSHA LDA #$0F ;3.1415926/2 PSHA LDA #$DB PSHA TST 8,SP BMI FSIN3 LDA 4,SP EOR #$80 STA 4,SP FSIN3: JSR FADD JSR FPLN FCB $B9,$10,$9C,$C8; -0.0001379131650664394 FCB $B9,$54,$46,$B3; -0.00020244233075985 FCB $3C,$0D,$6D,$CA; 0.008632133020496639 FCB $B9,$73,$5B,$0B; -0.0002320820290798563 FCB $BE,$2A,$91,$97; -0.1665710098242987 FCB $B7,$A0,$55,$DE; 0.00001911347250640758 FCB $3F,$80,$00,$0C; 1.000001442350691 FCB $B2,$98,$4E,$7A; -1.773081670375376D-8 FCB $FF LDX 3,SP LDA 4,SP BEQ FSIN4 LSLX LSLA LSL 5,SP ;Sign RORA RORX FSIN4: STA 11,SP STX 10,SP LDA 2,SP STA 9,SP LDA 1,SP STA 8,SP AIS #5 RTS FCOS: LDA 6,SP PSHA LDA 6,SP PSHA LDA 6,SP PSHA LDA 6,SP PSHA LDA #$3F PSHA LDA #$C9 PSHA LDA #$0F ;3.1415926/2 PSHA LDA #$DB PSHA JSR FSUB PULA STA 6,SP PULA STA 6,SP PULA STA 6,SP PULA STA 6,SP JMP FSIN FTAN: LDA 6,SP PSHA LDA 6,SP PSHA LDA 6,SP PSHA LDA 6,SP PSHA JSR FCOS LDA 10,SP PSHA LDA 10,SP PSHA LDA 10,SP PSHA LDA 10,SP PSHA JSR FSIN JSR FDIV LDA 4,SP STA 10,SP LDA 3,SP STA 9,SP LDA 2,SP STA 8,SP LDA 1,SP STA 7,SP AIS #4 RTS 6. 反正切函数子程序:FATN ①功能:计算 Y = arctan X。 入口:X在堆栈中。 出口:Y(弧度值)在堆栈中。 它需使用25字节堆栈区(含4字节浮点数X,2字节调用指令的返回地址)。 执行时间约670μs。 ②算法: 利用公式arctanX=-arctan(-X),arctanX=π/2-arctan(1/X),把X转换为0X1的值,再利用切比雪夫插值法计算: arctanX = -0.01223856*X8+0.10111264*X7-0.3009458*X6 + 0.3823059*X5 -0.06226118*X4 - 0.32148312*X3 - 0.00113343*X2 + 1.000042*X -0.0000002589 最后按按自变量的范围置符号或执行π/2-Y。 ③例: 入口时 X=1.5 ($3F,$C0,$00,$00),出口时,Y = arctanX=0.982793858 ($3F,$7B,$98,$60)。 误差:0.000000084. ④程序: *************************************************** * FATN: Arctangent Function Subroutine * * Y = arctan(X) (in RAD, -1.570796 ~ 1.570796) * * Entry: X in Stack * * Exit: Y in Stack * *************************************************** FATN: LDA 6,SP AND #$80 PSHA LDA 7,SP AND #$7F PSHA LDX 7,SP PSHX LDX 7,SP PSHX LDX 7,SP PSHX LSL 10,SP ROLA CMP #$7F BMI FATN1 INC 5,SP LDA #$3F PSHA LDA #$80 PSHA CLRA PSHA PSHA JSR FDIV FATN1: JSR FPLN FCB $BC,$48,$84,$3E; -0.01223856041964135 FCB $3D,$CF,$14,$25; 0.1011126431125103 FCB $BE,$9A,$15,$91; -0.3009458153821638 FCB $3E,$C3,$BD,$9A; 0.3823059470008079 FCB $BD,$7F,$05,$94; -0.06226117996008819 FCB $BE,$A4,$99,$6F; -0.3214831256383986 FCB $BA,$94,$8F,$A5; -0.001133431444428591 FCB $3F,$80,$01,$60; 1.000042044305768 FCB $B4,$8B,$07,$D8; -2.58964774735304D-7 FCB $FF LDA 5,SP LSRA BCC FATN2 LDA #$3F ;3.1415926/2 - Y -> Y PSHA LDA #$C9 PSHA LDA #$0F PSHA LDA #$DB PSHA JSR FSUB FATN2: LDA 1,SP STA 8,SP LDA 2,SP STA 9,SP LDA 3,SP STA 10,SP LDA 4,SP LSLA LSL 5,SP RORA STA 11,SP AIS #5 RTS |