发新帖我要提问
12
返回列表
打印

征集优秀的BIN转BCD的C51程序

[复制链接]
楼主: ljm810010
手机看帖
扫描二维码
随时随地手机跟帖
21
ljm810010|  楼主 | 2008-11-26 12:40 | 只看该作者 回帖奖励 |倒序浏览

莫非 耕在此行 的想法和我的一样?

我在18楼也说过写好了一个,不过也是汇编的。
先卖个关子,程序在下面,但有水印看不清,到时待 耕在此行 发表了以后,我再告知 去水印方法,对比一下思路是否一样。

使用特权

评论回复
22
耕在此行| | 2008-11-26 15:48 | 只看该作者

呵呵 我在开始写了

晚上发上来

使用特权

评论回复
23
耕在此行| | 2008-11-26 17:24 | 只看该作者

呵呵 草草写了下,

感觉还不如前面那个连续减的好.还是xhtxzxw 聪明
INT数据放在R6 R7中,dig3 dig2 dig1 dig0中.
BIN_BCD:    
    Mov    r3,    #0
    Mov    r0,    #1fh    ; 0x1f40 =8000
    Mov    r1,    #40h
    Mov    r2,    #08    ;
    Lcall    dig32_cal
    Mov    dig3    r3

    Mov    r3,    #0
    Mov    r0,    #03h    ; 0x320 =800
    Mov    r1,    #20h
    Mov    r2,    #08    ;
    Lcall    dig32_cal
    Mov    dig2    r3

    mov    a,     r7
    Mov    b,    #10
    div    ab
    Mov    dig1    a
    Mov    dig0    b

Dig32_cal:    Mov    a,    r7    
    Clr    c
    Subb    a,    r1    ; 减低位
    Mov    r5,    a    ;存低位结果
    Mov    a,    r6
    Subb    a,    r0    ; 减高位

    Jc    Dig3_rrc
    Mov    r7,    r5    ;存减x000结果
    Mov    r6,    a
    Mov    a,    r3
    Add    a,    r2
    Mov    r3,    a
Dig32_rrc:    
    Mov    a,    r2
    Jb    acc.0    Dig_end32
    Rr    a
    Mov    r2,    a
    clr    c
    Mov    a,    r0
    Rrc    a
    Mov    r0,    a
    Mov    a,    r1
    Rrc    a
    Mov    r1,    a
    AJmp    Dig3_cal
Dig32_end:
    ret
    

使用特权

评论回复
24
wh6ic| | 2008-11-26 17:53 | 只看该作者

两种思路


一. 用中颖的79F系列51核片子做,其内核直接支持 16/8 指令,其它几种支持16X16的也可以;

二. 用乘法来做 16/8:
    1。 Num X 4  --> 左移两位,不考虑高字节溢出(Num < 10000),四次8位加法
    2。 得到的中间结果乘以 41943 (65536 / 100 X 64 = 41943.04),四次8位乘法/四~五次加法
    3。 四舍五入得到32位中间结果的高16位(可能不能舍),其中高8位即为 Num / 100 的商,Num - 100 X 商 = 余数,一次8位乘法,两次减法
    4。 商和余数分别做 8/8 除法,得到四位分离的BCD数据
    5。 本法似乎有漏洞,欢迎查证。

三.本讨论已离题了,还继续?似乎新开帖子比较好。      btw -- 22楼的水印俺解开了 :-D

使用特权

评论回复
25
ljm810010|  楼主 | 2008-11-26 18:12 | 只看该作者

楼上强人,水印也解了!

呵呵,第二点思路不错,不过做一次16位乘法可能较慢,试试也好,看看速度如何。
PS:解了水印也可能很难看明程序,没加注释。再收集多几贴,到时再重新发上来吧!^_^

使用特权

评论回复
26
耕在此行| | 2008-11-27 18:44 | 只看该作者

ljm810010

你的水印怎么不消了?

使用特权

评论回复
27
ljm810010|  楼主 | 2008-11-27 18:50 | 只看该作者

消水印方法:在图右侧用鼠标左键快速点三下

或者按键盘CTRL+A
不是MS的IE游览器可能不能解不开喔。

使用特权

评论回复
28
dengm| | 2008-11-27 19:02 | 只看该作者

【非典】16 bits to packed BCD, 51 ASM. (计算方法)

【非典】16 bits to packed BCD, 51 ASM. 55周期/93字节(终结) 

  TEST_NUM  EQU 65535
  ORG 000H
    MOV R2, #LOW(TEST_NUM) ; #11111111B 
    MOV R3, #HIGH(TEST_NUM); #11111111B ; 65535
    CALL BIN2BCD
    SJMP $

;==================================
BIN2BCD:
    ;--------------------------------------*
    ;Input:  R3:R2 --- 16 bits bin         |
    ;                R2--Bit 0 to bit 7    |
    ;                R3--Bit 8 to bit 15   |
    ;Output: R7:R6:R5 --- 5 Dig Packed BCD |
    ;                     R5: 个位/十位    |
    ;                     R6: 百位/千位    |
    ;                     R7: 万位         |
    ;Usage:  PSW (C, AC, OV), Acc, B       |
    ;                                      |
    ;PS: 55 CYs only.  93 bytes            |
    ;           DengMiao  2007-4 Guangzhou |
    ;--------------------------------------*

    MOV A, R2
    ANL A, #00000011B
    MOV R6, A     ; R6 --- *1  (bit 0 to bit 1) (2 bits)    
    
    MOV A, R3
    RRC A
    MOV B, A
    MOV A, R2
    RRC A
    MOV C, B.0
    RRC A
    MOV R7, A    ; R7 --- *4  (bit 2 to bit 10) (8 bits)  

    MOV A, #25   ; 25 * 4 = 100
    XCH A, B
    RR A
    ANL A, #00111111B
    MOV R5, A    ; R5 --- *1024 (bit 11 to bit 15) (6 bits)
    RL A
    ADD A, R5
    XCH A, R7    ; R7 == 3 * R5   (<= 3*63=189 < 255)
                 ; A  --- *4
;------------------------------
    ADD A, R7    ; 4* (A + 3*R5)         
    JC BIN2BCD_L1
      SJMP BIN2BCD_L2
BIN2BCD_L1:
      INC R5     ; +1000
      ADD A, #6  ; +  24 (4*6)
BIN2BCD_L2:
    ADD A, R7   ;  4*(A + 3*R5 + 3*R5)= 4*A + 24*R5  
    JC BIN2BCD_L1B
      SJMP BIN2BCD_L2B
BIN2BCD_L1B:
      INC R5     ; +1000 
      ADD A, #6  ; +  24 (4*6)
BIN2BCD_L2B:
    ;MOV B, #25
    DIV AB       ; A  25 (4*25=100)   
    CJNE A, #10, BIN2BCD_L3  ; A<=25525=10
      INC R5     ; *1000
      CLR A
BIN2BCD_L3B:
    MOV R7, A    ; R7 --- *100  Bin/BCD  R7<=9 
                 ; B  --- *4    Bin      B <=24         
    MOV A, #10   
    XCH A, B     ; A  --- *4    Bin      B <=24         
  ;-------------
    ;RL A         ; A*4
    ;RL A         ; A  --- *1    Bin      A <=4*24=96
    ;ORL A, R6    ; R6 --- *1    Bin/BCD  R6<=3 
    ;             ; A  --- *1    Bin      A<=96+3=99
    ;DIV AB
    ;SWAP A
    ;ORL A, B
    ;XCH A, R5    ; R5 --- *1    BCD    个位/十位     
    ;             ; A  --- *1000 Bin    A<=65 
    ;MOV B, #10
    ;--------------  
     ADD A, #(BIN2BCD_DB - $ - 3)
     MOVC A, @A+PC
     ADD A, R6
     DA A
     XCH A, R5     ; R5 --- *1    BCD    个位/十位     
                   ; A  --- *1000 Bin    A<=65 
  ;--------------------------
    DIV AB
    XCH A, R7    ; R7 --- *10000 bin/BCD 万位 R7<=6
                 ; A  --- *100  Bin/BCD  A<=9
                 ; B  --- *1000 Bin/BCD  B<=9
    SWAP A       
    ORL A, B
    SWAP A
    MOV R6, A   ; R6  --- *100  BCD   百位/千位   
    RET
BIN2BCD_L3:
    SJMP BIN2BCD_L3B
BIN2BCD_DB:
    DB 00H, 04H, 08H, 12H, 16H
    DB 20H, 24H, 28H, 32H, 36H
    DB 40H, 44H, 48H, 52H, 56H
    DB 60H, 64H, 68H, 72H, 76H
    DB 80H, 84H, 88H, 92H, 96H

;----------END OF BIN2BCD-------

  END
 
算法说明: 

把16bits, 分为3段:
     X -- Bit 10 到 Bit 15, 共 6 bits; (0 - 63)      *1024
     Y -- Bit 2 到 Bit 9,   共 8 bits; (0 - 255)     *4
     Z -- Bit 0 到 Bit 1,   共 2 bits; (0 - 3)       *1

可得到:
     1024 * X + 4 * Y + Z

   = 1000 * X + 24 * X + 4 * Y + Z

   = 1000 * X + 4 * ( 6 * X + Y ) + Z

   = 1000 * X + 4 * [ Y + (3*X) + (3*X)] + Z


  其中 X 的范围为 0 -- 63, 那么(3*X)的范围就为 0 -- 189, <255 (1 byte)
Y+(3*X) 如进位就 X 加1, [Y+(3*X)]-256 加 6, (因为 24 = 4 * 6).
另外, {[Y + (3*x)] - 256}+6 < 255 .

  = 1000 * (X+i) + 4 * {[Y + (3*x) + (3*x)] + 6 * i } + Z

  =   1000 * (X+i)
     + 100 * {[Y+3*X+3*X+6*i]  25 }
     + 4 * {[Y+3*X+3*X+6*i] MOD  25 }  + Z

其中   i          范围为    0 -- 2
     {[Y+3*X+3*X+6*i]  25 } <= 10
     4 * {[Y+3*X+3*X+6*i] MOD  25 }  + Z <= 99


 
 

使用特权

评论回复
29
dengm| | 2008-11-27 19:18 | 只看该作者

上面的代码已高度"速度优化", 应已达到速度 极限!!!

看不懂的, 可看 21IC 2007年4月, 本版的原始贴们.

使用特权

评论回复
30
hotpower| | 2008-11-27 19:45 | 只看该作者

dengm小心受批斗~~~A人莫言~~~

使用特权

评论回复
31
ljm810010|  楼主 | 2008-11-27 19:47 | 只看该作者

恐怖,的确是极限了。

看来我等之辈是坐井观天了

本以为把自己那个83周期的发上来,看来不必了

会不会又是菜农的作品呢?发个原贴链接吧!

使用特权

评论回复
32
dengm| | 2008-11-27 19:52 | 只看该作者

re 4 楼

dig1 = Number % 100;

========>
dig1 = Number - dig0 * 100

使用特权

评论回复
33
ljm810010|  楼主 | 2008-11-27 20:08 | 只看该作者

看到了,呵呵!向上面两位前辈致敬!

使用特权

评论回复
34
ljm810010|  楼主 | 2008-11-27 20:30 | 只看该作者

佩服得五体投地。

如果Dengm同志在微软工作,我们的电脑可以快百倍。

使用特权

评论回复
35
hotpower| | 2008-11-27 21:02 | 只看该作者

51A人要数dengm同志~~~要挑战至少差250个周期~~~

使用特权

评论回复
36
wh6ic| | 2008-11-29 11:32 | 只看该作者

dengm兄,软件看了,思路超级佩服,但

  贱文谢谢指点,受教了.
另外:
 1. 软件中有几个跳转那样写有什么特殊意义?(乱猜的,跟定时有关?)
  
 2. 截取贵文
    ;MOV B, #10
    ;--------------  
     ADD A, #(BIN2BCD_DB - $ - 3)     ;A <= 24
     MOVC A, @A+PC                    ;A = (BCD) A X 4 <= 0x96
     ADD A, R6                        ;-- R6 <= 3, A + R6 不会产生十进制进位
     DA A
    ;--------------------------

 此处 DA A 语句可以省掉, 如此连其他修改可以做到 50t/86bytes(其实俺比较厚脸皮, 就省了条 DA A).

使用特权

评论回复
37
ljm810010|  楼主 | 2008-11-29 12:26 | 只看该作者

我来解读下吧,呵呵

楼上对DA A的理解有误了
     ADD A, #(BIN2BCD_DB - $ - 3)     ;A <= 24
     MOVC A, @A+PC                    ;A = (BCD) A X 4 <= 0x96(这句执行后,A的内容是数据表内容)
     ADD A, R6                        ;-- R6 <= 3, A + R6 
     DA A     ;(数据表内容和R6相加,是有可能产生半进位,不能省掉)

PS:几个无用的SJPM,是匹配时间,使R2R3为任意值,转换时间都相同.

不知我理解是否有错,呵呵


使用特权

评论回复
38
wh6ic| | 2008-11-29 15:30 | 只看该作者

按现表值加三都不可能产生半进位,更不用说进位

使用特权

评论回复
39
ljm810010|  楼主 | 2008-11-29 16:22 | 只看该作者

08h,28h,48h,68h,88h加三都要进位,逢十进出一

使用特权

评论回复
40
dengm| | 2008-11-29 16:26 | 只看该作者

RE: wh6ic: ljm810010 是完全正确的.

数据表: 08h, 28h, 48h, 68h, 88h时, ADD A, R6 后, 就要用 DA A 进行BCD调整

SJMP 是调运行周期的

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则