cpubbs 发表于 2004-11-1 18:15:53

吐血推荐!!!(附源程序)MSC51的FTOD (zz)

;程序说明:浮点数变为压缩BCD码,保存在以数组中
;         第1字节的位7:0正,1负.位6:0(位5--0代表小数点前的位数),1(位5--0代表小数
点后0的位数)
;         2--4字节为压缩BCD码,有效位为7位,3个半字节,最后半个字节请使用者自行放
弃
;         程序占用资源PSW,A,B,DPTR,R0--R7,SP深度6,RAM 5个放数据
;         keil 兼容,调用KEIL 的FPMUL子程序。
;程序作者:*************陈远征**************
;目    的:追求更快的执行速度,与最小的程序代码
;发布时间:2003--05--08
;编写背景:精通汇编,研究C51半个月。身感C51方便中的不便
;         研究了几种汇编及KEIL的浮点算法,特做此程序.
;声    明:转载时请保留以上的信息

C程序:
extern float ftod(float i);

unsigned char cyz;

main(){
   float i=1234.567;
   ftod(i);
while(1);
      }

汇编程序:

PUBLIC   _FTOD          ;程序段
FTODP    SEGMENT CODE   ;入口地址
RSEG   FTODP          ;程序段

EXTRN   CODE(?C?FPMUL)
EXTRN    DATA(CYZ)
_FTOD:            ;参数传递在R4--R7中,浮点数IEEE标准seeeeeee emmmmmmm
mmmmmmmm mmmmmmmm
FTOD:
         MOV   A,R4       ;保存数符
         RLC   A               
         CLR   A            
         RRC   A            
         MOV   CYZ,A
         MOV   A,R4       ;取绝对值
         CLR   ACC.7
         MOV   R4,A
         ORL   A,R5
   JNZ   FCMP_1E10
         MOV   CYZ,#0      ;数值为0
         MOV   CYZ+1,#0
         MOV   CYZ+2,#0
         MOV   CYZ+3,#0
         MOV   CYZ+4,#0
   RET
FCMP_1E10:
         MOV   DPTR,#YUANZHENG_DE10
         LCALL   FR0DPTR               ;数值装入R0--R3
         LCALL   FCMP
         JNC   FCMP_1E0            ;数值小于等于1e10,跳
         MOV   DPTR,#YUANZHENG_DE_10 ;数值大于1e10,X=X*(1e-10)
         LCALL   FR0DPTR               ;数值1e-10装入R0--R3
         LCALL   ?C?FPMUL            ;keil的浮点数乘法
         MOV   A,CYZ
         CLR   ACC.6
         ADD   A,#10
         MOV   CYZ,A
         JMP   FCMP_1E10
FCMP_1E0:
         MOV   DPTR,#YUANZHENG_DE0
         LCALL   FR0DPTR               ;数值装入R0--R3
         LCALL   FCMP
         JZ      FCMP_1E0_10         ;数值等于1e0,跳
         JC      FCMP_1E0_10         ;数值大于1e0,跳
         MOV   DPTR,#YUANZHENG_DE10;数值小于1e0,X=X*(1e10)
         LCALL   FR0DPTR               ;数值1e10装入R0--R3
         LCALL   ?C?FPMUL            ;keil的浮点数乘法
         MOV   A,CYZ
         SETB    ACC.6
         ADD   A,#10
         MOV   CYZ,A
         JMP   FCMP_1E10
FCMP_1E0_10:                           ;查表,找到一个比待转换浮点数大的整数幂.
         MOV   DPTR,#YUANZHENG_DE0
FCMP_FIND:                  
         LCALL   FR0DPTR
         LCALL   FCMP
         JNZ   FCMP_UNEQU
         MOV   CYZ+1,#10H            ;正好是表格中的数,尾数为0.10000000
         MOV   CYZ+2,#00H
         MOV   CYZ+3,#00H
         MOV   CYZ+4,#00H
   LCALL   CYZDEAL_JIE
         RET   
FCMP_UNEQU:
         JC      FCMP_NEXT            ;待转换浮点数大,跳转
         MOV   CYZ+1,DPH            ;a,b,c    a=b-(c-b)
         MOV   CYZ+2,DPL
         MOV   DPTR,#YUANZHENG_DE0
         CLR   C
         MOV   A,CYZ+2
         SUBB    A,DPL
         MOV   CYZ+2,A
         MOV   A,CYZ+1
         SUBB    A,DPH
         MOV   CYZ+1,A
         CLR   C
         MOV   A,DPL
         SUBB    A,CYZ+2
         MOV   DPL,A
         MOV   A,DPH
         SUBB    A,CYZ+1
         MOV   DPH,A
         INC   DPTR
         INC   DPTR
         INC   DPTR
         INC   DPTR
         LCALL   FR0DPTR               ;数值1e?装入R0--R3
         LCALL   ?C?FPMUL            ;keil的浮点数乘法
         JMP   YUANZHENG_FBCD      ;得到一个二进制浮点数的纯小数。
FCMP_NEXT:
         MOV   A,CYZ               ;幂值调整
         JB      ACC.6,FCMP_NEXT1
         INC   CYZ
         JMP   FCMP_FIND
FCMP_NEXT1:
         DEC   CYZ
         JMP   FCMP_FIND

YUANZHENG_FBCD:
         MOV   A,R5       ;恢复阶码
         RLC   A
         MOV   A,R4
         RLC   A
         CLR   C
         SUBB    A,#126
         MOV   R4,A
         MOV   A,R5       ;恢复尾数
         SETB    ACC.7
         MOV   R5,A
CYZFTB0:
         MOV   A,R4       ;取阶码
         JZ      CYZFTB1    ;为零吗?
   CLR    C
   LCALL    RR1         ;右规。
   SJMP    CYZFTB0
CYZFTB1:
         ACALL   HB2      ;转换尾数的十分位和百分位
         MOV   CYZ+1,A
         ACALL   HB2      ;转换尾数的千分位和万分位
         MOV   CYZ+2,A
         ACALL   HB2      ;转换尾数的十万分位和百万分位
         MOV   CYZ+3,A
         ACALL   HB2      ;转换尾数的千万分位和亿分位
         MOV   CYZ+4,A

      MOV    A,R5      ;四舍五入。
   RLC    A
   MOV   A,#05H   ;此处后半字节(BCD码的第8位)的值不保证
   ADDC    A,CYZ+4
   DA    A
   MOV    CYZ+4,A
   CLR    A
   ADDC    A,CYZ+3
   DA    A
   MOV    CYZ+3,A
   CLR    A
   ADDC    A,CYZ+2
   DA    A
   MOV    CYZ+2,A
   CLR    A
   ADDC    A,CYZ+1
   DA    A
   MOV    CYZ+1,A
   JNC    CYZFTB2
   MOV    CYZ+1,#10H
   LCALL   CYZDEAL_JIE      ;十进制浮点数的阶码。
CYZFTB2:   
         RET
CYZDEAL_JIE:
         MOV   A,CYZ            ;幂值调整
         JNB      ACC.6,CYZDEAL_JIE1
         DEC   CYZ
         RET
CYZDEAL_JIE1:
         INC   CYZ
         RET

RR1:   MOV    A,R5       ;第一操作数右规一次
   RRC    A       ;尾数缩小一半
   MOV    R5,A
   MOV    A,R6
   RRC    A
   MOV    R6,A
   MOV    A,R7
      RRC    A
   MOV    R7,A
   INC    R4         ;阶码加一
   CLR    OV         ;清溢出标志
   CJNE    R4,#80H,RR1E ;阶码上溢否?
   MOV    R4,#7FH         ;阶码溢出
   SETB    OV
RR1E:   RET

HB2:   
         MOV    A,R7    ;尾数扩大100倍。
   MOV    B,#100
   MUL    AB
   MOV    R7,A
   MOV    A,B
   XCH    A,R6
   MOV    B,#100
   MUL    AB
   ADD    A,R6
   MOV    R6,A
   MOV    A,B
   XCH    A,R5
   MOV    B,#100
   MUL    AB
   ADD    A,R5
   MOV    R5,A
   JNC    HB21
   INC    B
HB21:   MOV    A,B    ;将整数部分转换成BCD码。
   MOV    B,#10
   DIV    AB
   SWAP    A
   ORL    A,B
   RET
FR0DPTR:
         CLR   A
         MOVC    A,@A+DPTR
         MOV   R0,A
         INC   DPTR
         CLR   A
         MOVC    A,@A+DPTR
         MOV   R1,A
         INC   DPTR
         CLR   A
         MOVC    A,@A+DPTR
         MOV   R2,A
         INC   DPTR
         CLR   A
         MOVC    A,@A+DPTR
         MOV   R3,A
         INC   DPTR
         RET
FCMP:                  ;比较两个正的浮点数
         CLR   C
         MOV   A,R0
         SUBB    A,R4
         JNZ   FCMP1
         MOV   A,R1
         SUBB    A,R5
         JNZ   FCMP1
         MOV   A,R2
         SUBB    A,R6
         JNZ   FCMP1
         MOV   A,R3
         SUBB    A,R7
FCMP1:
         RET

YUANZHENG_DE_10:
         DB 02EH,0DBH,0E6H,0FFH ;1E-10
         DB 030H,089H,070H,05FH ;1E-9
         DB 032H,02BH,0CCH,077H ;1E-8
         DB 033H,0D6H,0BFH,095H ;1E-7
         DB 035H,086H,037H,0BDH ;1E-6
         DB 037H,027H,0C5H,0ACH ;1E-5
         DB 038H,0D1H,0B7H,017H ;1E-4
         DB 03AH,083H,012H,06FH ;1E-3
         DB 03CH,023H,0D7H,00AH ;1E-2
         DB 03DH,0CCH,0CCH,0CDH ;1E-1
YUANZHENG_DE0:
         DB 03FH,080H,000H,000H ;1E0
         DB 041H,020H,000H,000H ;1E1
         DB 042H,0C8H,000H,000H ;1E2
         DB 044H,07AH,000H,000H ;1E3
         DB 046H,01CH,040H,000H ;1E4
         DB 047H,0C3H,050H,000H ;1E5
         DB 049H,074H,024H,000H ;1E6
         DB 04BH,018H,096H,080H ;1E7
         DB 04CH,0BEH,0BCH,020H ;1E8
         DB 04EH,06EH,06BH,028H ;1E9
YUANZHENG_DE10:
         DB 050H,015H,002H,0F9H ;1E10


       END
页: [1]
查看完整版本: 吐血推荐!!!(附源程序)MSC51的FTOD (zz)