home *** CD-ROM | disk | FTP | other *** search
/ PC World 1997 November / PCWorld_1997-11_cd.bin / software / sharware / utility / PACKERS / LZH / LHASRC.EXE / DHUF_.ASM < prev    next >
Assembly Source File  |  1991-03-03  |  12KB  |  689 lines

  1. ;***********************************************
  2. ;    dhuf_.asm -- Dynamic Huffman routine
  3. ;***********************************************
  4.             page    0, 128
  5.  
  6. include    amscls.inc
  7. $_init    GEN
  8.  
  9. CGROUP  GROUP   TEXT
  10. DGROUP  GROUP   DATA,BSS
  11.  
  12. TEXT    segment byte public 'CODE'
  13.         assume  cs:CGROUP, ds:DGROUP, ss:DGROUP
  14. TEXT    ends
  15.  
  16. DATA    segment word public 'DATA'
  17. DATA    ends
  18.  
  19. THRESHOLD    equ        3
  20. N_CHAR        equ        (256 + 60 - THRESHOLD + 1)
  21. TREESIZE_C  equ        (N_CHAR * 2)
  22. TREESIZE_P  equ        (128 * 2)
  23. TREESIZE    equ        (TREESIZE_C + TREESIZE_P)
  24. ROOT_C      equ        0
  25. ROOT_P      equ        TREESIZE_C
  26.  
  27. BSS     segment word public 'DATA'
  28.         public  node_
  29. node_            dw      N_CHAR + 128 dup (?)
  30.         public  total_p_
  31. total_p_        dw        1 dup (?)
  32.  
  33. BSS     ends
  34.  
  35. BSS            segment word public 'DATA'
  36. start_        dw        1 dup(?)
  37. end_        dw        1 dup(?)
  38. BSS            ends
  39.  
  40. DATA    segment word public 'DATA'
  41. DATA    ends
  42.  
  43. BSS     segment word public 'DATA'
  44.         public  n_max_
  45. n_max_            dw        1 dup (?)
  46.         public  avail_
  47. avail_          dw      1 dup (?)
  48.         public  n1_
  49. n1_             dw      1 dup (?)
  50.         public  most_p_
  51. most_p_         dw      1 dup (?)
  52.         public  nn_
  53. nn_             dw      1 dup (?)
  54.         public  nextcount_
  55. nextcount_      dw      2 dup (?)
  56.  
  57. BSS     ends
  58.  
  59. TEXT    segment byte public 'CODE'
  60.  
  61. ;
  62. ;void start_c_dyn(void)
  63. ;
  64.  
  65.         public  start_c_dyn_
  66. start_c_dyn_    proc    near
  67.     push    cx
  68.     push    dx
  69.     push    si
  70.     push    di
  71.     mov        bx, 512
  72.     mov        ax, maxmatch_
  73.     add        ax, 256 - 2
  74.     $_if <cmp n_max_, ax>, B
  75.         mov        bx, n_max_
  76.         dec        bx
  77.     $_endif
  78.     mov        n1_, bx
  79.     push    ds
  80.     pop        es
  81.     cld
  82.     xor        ax, ax
  83.     mov        cx, TREESIZE_C
  84.     mov        di, offset DGROUP:block_
  85.     rep        stosw
  86.     mov        cx, TREESIZE_C
  87.     mov        di, offset DGROUP:stock_
  88.     $_do
  89.         stosw
  90.         inc        ax
  91.         inc        ax
  92.     $_until <LOOP>
  93.     mov        di, offset DGROUP:node_
  94.     mov        bx, n_max_
  95.     mov        cx, bx
  96.     dec        bx
  97.     shl        bx, 1
  98.     mov        edge_[2], bx
  99.     shl        bx, 1
  100.     push    bx
  101.     mov        ax, 1
  102.     mov        dx, 0ffffh
  103.     $_do
  104.         mov        freq_[bx], ax
  105.         mov        block_[bx], 2
  106.         mov        child_[bx], dx
  107.         mov        [di], bx
  108.         dec        dx
  109.         dec        dx
  110.         dec        bx
  111.         dec        bx
  112.         inc        di
  113.         inc        di
  114.     $_until <LOOP>
  115.     mov     word ptr DGROUP:[avail_], 4
  116.     pop        di
  117.     $_do
  118.         mov        ax, freq_[di]
  119.         add        ax, freq_[di - 2]
  120.         mov        freq_[bx], ax
  121.         mov        child_[bx], di
  122.         mov        parent_[di], bx
  123.         mov        parent_[di - 2], bx
  124.         $_if <cmp ax, freq_[bx + 2]>, E
  125.             mov        si, block_[bx + 2]
  126.         $_else
  127.             mov        si, avail_
  128.             add        avail_, 2
  129.             mov        si, stock_[si]
  130.         $_endif
  131.         mov        block_[bx], si
  132.         mov        edge_[si], bx
  133.         sub        di, 4
  134.         dec        bx
  135.         dec        bx
  136.     $_until , S
  137.     pop        di
  138.     pop        si
  139.     pop        dx
  140.     pop        cx
  141.     ret
  142. start_c_dyn_    endp
  143.  
  144.  
  145. ;
  146. ;static void start_p_dyn(void)
  147. ;
  148.  
  149. start_p_dyn_    proc    near
  150.     push    cx
  151.     mov     freq_[ROOT_P * 2], 1
  152.     mov     child_[ROOT_P * 2], not (N_CHAR * 2)
  153.     mov     node_[N_CHAR * 2], ROOT_P * 2
  154.     mov        bx, avail_
  155.     add        avail_, 2
  156.     mov        bx, stock_[bx]
  157.     mov        block_[ROOT_P * 2], bx
  158.     mov        edge_[bx], ROOT_P * 2
  159.     mov        most_p_, ROOT_P * 2
  160.     mov        ax, 1
  161.     mov        cx, dicbit_
  162.     shl        ax, cl
  163.     mov        nn_, ax
  164.     xor        ax, ax
  165.     mov        nextcount_, 64
  166.     mov        nextcount_[2], ax
  167.     mov        total_p_, 0
  168.     pop        cx
  169.     ret
  170. start_p_dyn_    endp
  171.  
  172.  
  173. ;
  174. ;void decode_start_dyn(void)
  175. ;
  176.  
  177.             public  decode_start_dyn_
  178. decode_start_dyn_    proc    near
  179.     mov        n_max_, 286
  180.     mov        maxmatch_, 256
  181.     call    init_getbits_
  182.     call    start_c_dyn_
  183.     call    start_p_dyn_
  184.     ret
  185. decode_start_dyn_    endp
  186.  
  187.  
  188. ;
  189. ;static void reconst(int start, int end)
  190. ;
  191.  
  192.             public    reconst_
  193. reconst_    proc    near
  194.     push    cx
  195.     push    dx
  196.     push    si
  197.     push    di
  198.     mov        start_, ax
  199.     mov        end_, bx
  200.     mov        si, ax
  201.     mov        di, ax
  202.     $_while <cmp si, end_>, L
  203.         mov        bx, child_[si]
  204.         $_if <or bx, bx>, L
  205.             mov        ax, freq_[si]
  206.             inc        ax
  207.             shr        ax, 1
  208.             mov        freq_[di], ax
  209.             mov        child_[di], bx
  210.             inc        di
  211.             inc        di
  212.         $_endif
  213.         mov        bx, block_[si]
  214.         $_if <cmp edge_[bx], si>, E
  215.             sub        avail_, 2
  216.             mov        ax, bx
  217.             mov        bx, avail_
  218.             mov        stock_[bx], ax
  219.         $_endif
  220.         inc        si
  221.         inc        si
  222.     $_enddo
  223.     dec        di
  224.     dec        di
  225.     dec        si
  226.     dec        si
  227.     mov        bx, si
  228.     dec        bx
  229.     dec        bx
  230.     $_while <cmp si, start_>, GE
  231.         $_while <cmp si, bx>, GE
  232.             mov        ax, freq_[di]
  233.             mov        freq_[si], ax
  234.             mov        ax, child_[di]
  235.             mov        child_[si], ax
  236.             dec        di
  237.             dec        di
  238.             dec        si
  239.             dec        si
  240.         $_enddo
  241.         mov        ax, freq_[bx]
  242.         add        ax, freq_[bx + 2]
  243.         push    bx
  244.         mov        bx, start_
  245.         $_while <cmp ax, freq_[bx]>, B
  246.             inc        bx
  247.             inc        bx
  248.         $_enddo
  249.         $_while <cmp di, bx>, GE
  250.             mov        dx, freq_[di]
  251.             mov        freq_[si], dx
  252.             mov        dx, child_[di]
  253.             mov        child_[si], dx
  254.             dec        si
  255.             dec        si
  256.             dec        di
  257.             dec        di
  258.         $_enddo
  259.         mov        freq_[si], ax
  260.         pop        bx
  261.         inc        bx
  262.         inc        bx
  263.         mov        child_[si], bx
  264.         dec        si
  265.         dec        si
  266.         sub        bx, 6
  267.     $_enddo
  268.     xor        ax, ax
  269.     mov        si, start_
  270.     $_while <cmp si, end_>, L
  271.         mov        di, child_[si]
  272.         $_if <or di, di>, S
  273.             not        di
  274.             mov        node_[di], si
  275.             not        di
  276.         $_else
  277.             mov        parent_[di], si
  278.             mov        parent_[di - 2], si
  279.         $_endif
  280.         mov        dx, freq_[si]
  281.         $_if <cmp dx, ax>, E
  282.             mov        block_[si], bx
  283.         $_else
  284.             mov        bx, avail_
  285.             add        avail_, 2
  286.             mov        bx, stock_[bx]
  287.             mov        block_[si], bx
  288.             mov        edge_[bx], si
  289.             mov        ax, dx
  290.         $_endif
  291.         inc        si
  292.         inc        si
  293.     $_enddo
  294.     pop        di
  295.     pop        si
  296.     pop        dx
  297.     pop        cx
  298.     ret
  299. reconst_    endp
  300.  
  301. ;
  302. ;    static int swap_inc(int p)
  303. ;
  304.  
  305.             public    swap_inc_
  306. swap_inc_    proc    near
  307. ;    push    dx
  308. ;    push    si
  309. ;    push    di
  310.     mov        si, ax
  311.     mov        bx, block_[si]
  312.     mov        di, edge_[bx]
  313.     $_if <cmp di, si>, NE
  314.         push    bx
  315.         mov        bx, child_[si]
  316.         mov        dx, child_[di]
  317.         mov        child_[si], dx
  318.         mov        child_[di], bx
  319.         $_if <or bx, bx>, NS
  320.             mov        parent_[bx], di
  321.             mov        parent_[bx - 2], di
  322.         $_else
  323.             not        bx
  324.             mov        node_[bx], di
  325.         $_endif
  326.         mov        bx, dx
  327.         $_if <or bx, bx>, NS
  328.             mov        parent_[bx], si
  329.             mov        parent_[bx - 2], si
  330.         $_else
  331.             not        bx
  332.             mov        node_[bx], si
  333.         $_endif
  334.         mov        si, di
  335.         pop        bx
  336.         jmp        Adjust
  337.     $_endif
  338.     $_if <cmp bx, block_[si + 2]>, E
  339. Adjust:
  340.         add        edge_[bx], 2
  341.         inc        freq_[si]
  342.         mov        ax, freq_[si]
  343.         $_if <cmp ax, freq_[si - 2]>, E
  344.             mov        ax, block_[si - 2]
  345.             mov        block_[si], ax
  346.         $_else
  347.             mov        bx, avail_
  348.             add        avail_, 2
  349.             mov        bx, stock_[bx]
  350.             mov        block_[si], bx
  351.             mov        edge_[bx], si
  352.         $_endif
  353.     $_else
  354.         inc        freq_[si]
  355.         mov        ax, freq_[si]
  356.         $_if <cmp ax, freq_[si - 2]>, E
  357.             sub        avail_, 2
  358.             mov        di, avail_
  359.             mov        stock_[di], bx
  360.             mov        ax, block_[si - 2]
  361.             mov        block_[si], ax
  362.         $_endif
  363.     $_endif
  364.     mov        ax, parent_[si]
  365. ;    pop        di
  366. ;    pop        si
  367. ;    pop        dx
  368.     ret
  369. swap_inc_    endp
  370.  
  371.  
  372. ;
  373. ;    static void update_c(int p)
  374. ;
  375.  
  376.             public    update_c_
  377. update_c_    proc    near
  378.     $_if <cmp freq_[ROOT_C * 2], 8000h>, E
  379.         push    ax
  380.         mov        bx, n_max_
  381.         shl        bx, 1
  382.         dec        bx
  383.         shl        bx, 1
  384.         xor        ax, ax
  385.         call    reconst_
  386.         pop        ax
  387.     $_endif
  388.     inc        freq_[ROOT_C * 2]
  389.     mov        bx, ax
  390.     mov        ax, node_[bx]
  391.     $_do
  392.         call    swap_inc_
  393.     $_until <cmp ax, ROOT_C * 2>, E
  394.     ret
  395. update_c_    endp
  396.  
  397.  
  398. ;
  399. ;    static void update_p(int p)
  400. ;
  401.  
  402.             public    update_p_
  403. update_p_    proc    near
  404.     $_if <cmp total_p_, 8000h>, E
  405.         push    ax
  406.         mov        bx, most_p_
  407.         inc        bx
  408.         inc        bx
  409.         mov        ax, ROOT_P * 2
  410.         call    reconst_
  411.         mov        ax, 0ffffh
  412.         xchg    ax, freq_[ROOT_P * 2]
  413.         mov        total_p_, ax
  414.         pop        ax
  415.     $_endif
  416.     mov        bx, ax
  417.     mov        ax, node_[bx + N_CHAR * 2]
  418.     $_while <cmp ax, ROOT_P * 2>, NE
  419.         call    swap_inc_
  420.     $_enddo
  421.     inc        total_p_
  422.     ret
  423. update_p_    endp
  424.  
  425.  
  426. ;
  427. ;    static void make_new_node(int p)
  428. ;
  429.  
  430. make_new_node_    proc    near
  431.     push    si
  432.     push    di
  433.     mov        di, most_p_
  434.     mov        bx, child_[di]
  435.     mov        child_[di + 2], bx
  436.     not        bx
  437.     lea        si, [di + 2]
  438.     mov        node_[bx], si
  439.     mov        si, ax
  440.     add        si, N_CHAR * 2
  441.     not        si
  442.     mov        child_[di + 4], si
  443.     lea        si, [di + 4]
  444.     mov        child_[di], si
  445.     mov        bx, freq_[di]
  446.     mov        freq_[di + 2], bx
  447.     mov        freq_[di + 4], 0
  448.     mov        bx, block_[di]
  449.     mov        block_[di + 2], bx
  450.     $_if <cmp di, ROOT_P * 2>, E
  451.         mov        freq_[ROOT_P * 2], 0ffffh
  452.         mov        bx, block_[ROOT_P * 2]
  453.         add        edge_[bx], 2
  454.     $_endif
  455.     mov        parent_[di + 2], di
  456.     mov        parent_[di + 4], di
  457.     add        di, 4
  458.     mov        most_p_, di
  459.     mov        bx, ax
  460.     mov        node_[bx + N_CHAR * 2], di
  461.     mov        bx, avail_
  462.     add        avail_, 2
  463.     mov        bx, stock_[bx]
  464.     mov        block_[di], bx
  465.     mov        edge_[bx], di
  466.     call    update_p_
  467.     pop        di
  468.     pop        si
  469.     ret
  470. make_new_node_    endp
  471.  
  472.  
  473. ;
  474. ;    static void encode_c_dyn(int c)
  475. ;
  476.  
  477. encode_c_dyn_    proc    near
  478.     push    cx
  479.     push    dx
  480.     push    si
  481. ;    push    di
  482. ;    mov        di, -1
  483. ;    $_if <cmp ax, n1_>, AE
  484. ;        mov        di, ax
  485. ;        mov        ax, n1_
  486. ;        sub        di, ax
  487. ;    $_endif
  488.     shl        ax, 1
  489.     mov        bx, ax
  490.     mov        bx, node_[bx]
  491.     xor        dx, dx
  492.     mov        cx, dx
  493.     $_do
  494.         mov        si, bx
  495.         shr        bx, 1
  496.         shr        bx, 1
  497.         rcr        dx, 1
  498.         rcr        ch, 1
  499.         inc        cx
  500.         mov        bx, parent_[si]
  501.     $_until <cmp bx, ROOT_C * 2>, E
  502.     mov        si, ax
  503.     $_if <cmp cl, 16>, A
  504.         mov        bx, dx
  505.         mov        al, 16
  506.         sub        cl, al
  507.         call    putcode_
  508.         mov        dx, cx
  509.         xor        dl, dl
  510.     $_endif
  511.     mov        ax, cx
  512.     mov        bx, dx
  513.     call    putcode_
  514. ;    $_if <or di, di>, NS
  515. ;        mov        bx, di
  516. ;        mov        ax, 8
  517. ;        call    putbits_
  518. ;    $_endif
  519.     mov        ax, si
  520.     call    update_c_
  521. ;    pop        di
  522.     pop        si
  523.     pop        dx
  524.     pop        cx
  525.     ret
  526. encode_c_dyn_    endp
  527.  
  528. ;
  529. ;    ushort decode_c_dyn(void)
  530. ;
  531.  
  532.         public  decode_c_dyn_
  533. decode_c_dyn_    proc    near
  534.     push    cx
  535.     push    dx
  536.     push    si
  537.     push    di
  538.     mov        si, child_[ROOT_C * 2]
  539.     mov        cx, 16
  540.     mov        bx, bitbuf_
  541.     $_do
  542.         $_if <dec cx>, S
  543.             mov        ax, 16
  544.             mov        cx, 15
  545.             call    fillbuf_
  546.             mov        bx, bitbuf_
  547.         $_endif
  548.         shl        bx, 1
  549.         sbb        ax, ax
  550.         shl        ax, 1
  551.         add        si, ax
  552.         mov        si, child_[si]
  553.     $_until <or si, si>, LE
  554.     mov        al, 16
  555.     sub        al, cl
  556.     call    fillbuf_
  557.     not        si
  558.     mov        ax, si
  559.     push    si
  560.     call    update_c_
  561.     pop        si
  562.     shr        si, 1
  563.     $_if <cmp si, n1_>, E
  564.         mov        ax, 8
  565.         call    getbits_
  566.         add        si, ax
  567.     $_endif
  568.     mov        ax, si
  569.     pop        di
  570.     pop        si
  571.     pop        dx
  572.     pop        cx
  573.     ret
  574. decode_c_dyn_    endp
  575.  
  576.  
  577. ;
  578. ;    ushort decode_p_dyn(void)
  579. ;
  580.  
  581.         public  decode_p_dyn_
  582. decode_p_dyn_    proc    near
  583.     push    cx
  584.     push    dx
  585.     push    si
  586.     push    di
  587.     $_while <cmp nextcount_ + 2, 0>, E, AND
  588.     mov        ax, nextcount_
  589.     $_c <cmp count_, ax>, G
  590.         mov        cl, 6 - 1
  591.         shr        ax, cl
  592.         call    make_new_node_
  593.         add        nextcount_, 64
  594.         mov        ax, nextcount_
  595.         $_if <cmp ax, nn_>, AE
  596.             mov        ax, 0ffffh
  597.             mov        nextcount_, ax
  598.             mov        nextcount_ + 2, ax
  599.         $_endif
  600.     $_enddo
  601.     mov        si, child_[ROOT_P * 2]
  602.     mov        cx, 16
  603.     mov        bx, bitbuf_
  604.     $_while <or si, si>, G
  605.         $_if <dec cx>, S
  606.             mov        ax, 16
  607.             mov        cx, 15
  608.             call    fillbuf_
  609.             mov        bx, bitbuf_
  610.         $_endif
  611.         shl        bx, 1
  612.         sbb        ax, ax
  613.         shl        ax, 1
  614.         add        si, ax
  615.         mov        si, child_[si]
  616.     $_enddo
  617.     mov        al, 16
  618.     sub        al, cl
  619.     call    fillbuf_
  620.     not        si
  621.     sub        si, N_CHAR * 2
  622.     mov        ax, si
  623.     push    si
  624.     call    update_p_
  625.     mov        ax, 6
  626.     call    getbits_
  627.     pop        si
  628.     mov        cl, 6 - 1
  629.     shl        si, cl
  630.     add        ax, si
  631.     pop        di
  632.     pop        si
  633.     pop        dx
  634.     pop        cx
  635.     ret
  636. decode_p_dyn_    endp
  637.  
  638.  
  639. ;
  640. ;    void output_dyn(int code, unsigned int pos)
  641. ;
  642.  
  643.                 public    output_dyn_
  644. output_dyn_    proc    near
  645.     $_if <cmp ax, 100h>, AE
  646.         push    bx
  647.         call    encode_c_dyn_
  648.         pop        ax
  649.         jmp        encode_p_st0_
  650.     $_endif
  651.     jmp        encode_c_dyn_
  652. output_dyn_    endp
  653.  
  654.  
  655. ;
  656. ;    void encode_end_dyn(void)
  657. ;
  658.  
  659.         public  encode_end_dyn_
  660. encode_end_dyn_    proc    near
  661.     mov        al, 7
  662.     xor        bx, bx
  663.     jmp        putcode_
  664. encode_end_dyn_    endp
  665.  
  666.  
  667.         EXTRN   getbits_:near
  668.         EXTRN   fillbuf_:near
  669.         EXTRN   putcode_:near
  670.         EXTRN   putbits_:near
  671.         EXTRN   init_getbits_:near
  672.         EXTRN   encode_p_st0_:near
  673.  
  674. TEXT    ends
  675.  
  676.         EXTRN   dicbit_:word
  677.         EXTRN   count_:word
  678.         EXTRN   block_:word
  679.         EXTRN   parent_:word
  680.         EXTRN   child_:word
  681.         EXTRN   maxmatch_:word
  682.         EXTRN   freq_:word
  683.         EXTRN   stock_:word
  684.         EXTRN   edge_:word
  685.         EXTRN   maxmatch_:word
  686.         EXTRN   bitbuf_:word
  687.  
  688.         END
  689.