原创 菜农自贺5年后数组汇编82字节雷翻了dengm同志90字节的万年历汇编

2009-3-10 23:14 3294 0 分类: MCU/ 嵌入式
HotC51 发表于 2009-3-10 23:14 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

楼主: 菜农自贺5年后数组汇编82字节雷翻了dengm同志90字节的万年历汇编


/*-----------------------------------------------------------------------
        函数Week(macro_U16_arg1, macro_U8_arg2, macro_U8_arg3)
入口:
        macro_U16_arg1 年(0x00~0x9999)BCD码
        macro_U8_arg2  月(0x01~0x12)BCD码
        macro_U8_arg3  日(0x01~0x31)BCD码
出口:
        macro_U8_Result 星期(0~6)
长度:   82字节
-----------------------------------------------------------------------*/
macro_Function_Arg3 (Week, macro_U16_arg1, macro_U8_arg2, macro_U8_arg3)
{
#define Week_LOOP -20
    asm_MOV_R1(4),//将百年、年、月、日的BCD码换成二进制数
//Week_LOOP:
    asm_MOV_A(0x4f),//DataBuffer偏移,程序长度
//分别取出macro_U16H_arg1,macro_U16L_arg1macro_U8_arg2, macro_U8_arg3
    asm_MOVC_A_aDPTR(),
    asm_MOV_R0_A(),
    asm_MOV_A_iR0(),
    asm_ANL_A(0x0f),
    asm_XCH_A_iR0(),
    asm_SWAP_A(),
    asm_ANL_A(0x0f),
    asm_MOV_B(10),
    asm_MUL_AB(),
    asm_ADD_A_iR0(),
    asm_MOV_iR0_A(),
    asm_INC_DPTR(),
    asm_DJNZ_R1(Week_LOOP),//四次未完继续
//(星期=百年%4*5+年+年/4+(13*月+8)/5+日)%7,特别注意1月2月的年为"去年"
    asm_CJNE_Rn(macro_U8_arg2, 0x03, 0),//判断月
    asm_JNC(size_MOV_A_Rn() + size_ORL_A() + size_MOV_Rn_A() \
            + size_DEC_Rn() + size_CJNE_Rn() + size_DEC_Rn()),//月
//月<=2
    asm_MOV_A_Rn(macro_U8_arg2),
    asm_ORL_A(0x04),//1月2月同5月六月表
    asm_MOV_Rn_A(macro_U8_arg2),
    asm_DEC_Rn(macro_U16L_arg1),//1月2月的年为"去年"
    asm_CJNE_Rn(macro_U16L_arg1, 0xff, size_DEC_Rn()),//Week_Start
    asm_DEC_Rn(macro_U16H_arg1),
//Week_Start:
//百年%4*5
    asm_MOV_A_Rn(macro_U16H_arg1),//百年
    asm_ANL_A(0x03),
    asm_MOV_Rn_A(macro_U16H_arg1),//百年%4
    asm_CLR_C(),
    asm_RLC_A(),
    asm_CLR_C(),
    asm_RLC_A(),//百年%4*4
    asm_ORL_A_Rn(macro_U16H_arg1),//百年%4*5
    asm_MOV_Rn_A(macro_U16H_arg1),//保存(百年%4*5),最大值3*5=15
//年+年/4
    asm_MOV_A_Rn(macro_U16L_arg1),//年
    asm_CLR_C(),
    asm_RRC_A(),
    asm_CLR_C(),
    asm_RRC_A(),
    asm_ADD_A_Rn(macro_U16L_arg1),//年+年/4
    asm_MOV_Rn_A(macro_U16L_arg1),//保存(年+年/4),最大值99+25=124
    asm_MOV_A_Rn(macro_U8_arg2),//月
    asm_MOV_B(13),
    asm_MUL_AB(),//13*月->A
    asm_MOV_B(8),
    asm_ADD_A_B(),//13*月+8
    asm_MOV_B(5),
    asm_DIV_AB(),//(13*月+8)/5 商->A
    asm_MOV_Rn_A(macro_U8_arg2),//保存((13*月+8)/5)最大值33
//日
    asm_ADD_A_Rn(macro_U8_arg3),//日,最大值31
    asm_ADDC_A_Rn(macro_U16H_arg1),//(百年%4*5),最大值15
    asm_ADDC_A_Rn(macro_U16L_arg1),//(年+年/4),最大值99+25=124
/*
此时ACC最大为15+124+33+31=203,
注意,蔡勒公式内无203.-2*C可能会越界,菜农给出的蔡勒公式完整表述:
W = (203+C/4-2*C+Y+Y/4+(13*M+8)/5+D)%7
菜农星期公式:
W = (    C%4*5+Y+Y/4+(13*M+8)/5+D)%7
*/
    asm_MOV_B(7),//取余数%7
    asm_DIV_AB(),
    asm_XCH_A_B(),
    asm_MOV_Rn_A(macro_U8_Result),//送返回值(星期)
    macro_return(),
//数据区DataBuffer
    asm_DB(macro_U16H_arg1),
    asm_DB(macro_U16L_arg1),
    asm_DB(macro_U8_arg2),
    asm_DB(macro_U8_arg3)
};



高度代码大小优化的 万年历(90 bytes, 51 asm), 供参考


HotC51 发表于 2009-3-10 23:17 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

2楼: 坐等dengm同志PK数组汇编~~~郁闷他一个月都不上网了~~~


十分之苦闷~~~

高度代码大小优化的 万年历(90 bytes, 51 asm), 供参考
mood13.gif dengm 发表于 5/27/2004 8:20:41 PM 侃单片机 ←返回版面 按此给该网友发送邮件 按此察看该网友的资料 按此把文章加入收藏夹



真正的万年历: 90 bytes 的 51 ASM

;==SUB_WNL=== 万年历 ==* Deng Miao *  2004-05-27 ***** GuangZhou ******
          SJ    DATA   30H ; 世纪  BCD  00 TO 99   
          NH    DATA   31H ; 年号  BCD  00 TO 99    0000 TO 9999 年
          YF    DATA   32H ; 月份  BCD  01 TO 12

   org 000h
     MOV SP, #40H
     MOV SJ, #20H ;2004-05
     MOV NH, #04H
     MOV YF, #05H   
     ACALL SUB_WNL
     SJMP $   

;===============SUB_WNL===================
     ; 入口:
        ;  SJ    DATA   30H ; 世纪  BCD  00 TO 99   
        ;  NH    DATA   31H ; 年号  BCD  00 TO 99    0000 TO 9999 年
        ;  YF    DATA   32H ; 月份  BCD  01 TO 12
     ; 出口
        ; ACC   --  本月天数 BCD 28 to 31
        ; B     --  本月1日的星期数 1 to 6 == 星期1 to 星期6
        ;                                0 -- 星期日
     ; 使用 ACC, B, R5,R6
     ; STACK:  3 bytes (不包括调用)
      ORG 50H
      ; SJ/4  400年大周期
      ; DateDiff("d", #1/1/2000#, #1/1/2400#)
      ; =146097天 = 7 * 20871 + 0 天
      ; 100年 = 7 * 5217 + 6
      ; 200年 = 7 * 10435 + 4
      ; 300年 = 7 * 15653 + 2
      ;  

SUB_WNL:
      PUSH PSW
      MOV A, SJ
      ACALL BCD2BIN_DIV4      
      CPL A
      INC A
      ANL A, #03H
      RL A
      MOV R5, A  ; R5: 星期  0/6/4/2

      MOV A, NH
      JZ  WNL_1
         ACALL BCD2BIN_DIV4
WNL_1:
      MOV A, YF
      ADD A, #(WNL_TAB-$-4)
      MOVC A, @A+PC
      MOV R6, A
      SWAP A
      ACALL WNL_F0
      ADDC A, R5
      ;ADD A, #6;  0000-01-01 星期 6
      MOV B, #7
      DIV AB
      MOV A, R6
      ACALL WNL_F0
      ADDC A, #28
      POP PSW
      RET

WNL_TAB:
      DB 3*2 + 6 * 32+0 ;1
      DB 0*2+1 + 2 * 32+0 ;2
      DB 3*2 + 2 * 32+16 ;3
      DB 2*2 + 5 * 32+16 ;4
      DB 3*2 + 0 * 32+16 ;5
      DB 2*2 + 3 * 32+16 ;6
      DB 3*2 + 5 * 32+16 ;7
      DB 3*2 + 1 * 32+16 ;8
      DB 2*2 + 3 * 32+16 ;9
WNL_F0:        ; 6 BYTES ;
        RRC A            ;0AH
        ANL A, #07H      ;0BH
                         ;0CH
        ANL C, F0        ;0DH
                         ;0EH
        RET              ;0FH
      DB 3*2 + 5 * 32+16 ;10H
      DB 2*2 + 1 * 32+16 ;11H
      DB 3*2 + 3 * 32+16 ;12H

BCD2BIN_DIV4:
      MOV R6, A
      ANL A, #0F0H
      SWAP A
      
      MOV B, #(256-6)
      MUL AB
      ADD A, R6
      MOV B, #4
      DIV AB
      MOV R6, B

      ;-------------------------------------
      MOV B, #5  ; 3 * 365 + 366 = 7*208 + 5
      MUL AB
      
      ADD A, R6  ; 366 = 7*52 + 2
                 ; 366 + 365 = 7*104 + 3
                 ; 366 + 365 + 365 = 7*156+4
      MOV C, F0
      ADDC  A, R5
      MOV R5, A
      MOV A, R6
      JNZ WNL_EXT
        DEC R5
        SETB C
WNL_EXT:      
      MOV F0, C
      RET
      ;-----------------------------
   END ;======== END OF FILE



http://www.21icbbs.com/club/bbs/ShowAnnounce.asp?v=&ID=1205262
PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
0
关闭 站长推荐上一条 /3 下一条