home *** CD-ROM | disk | FTP | other *** search
/ FreeWare Collection 2 / FreeSoftwareCollection2pd199x-jp.img / fbasic / pmgf / compress.asm next >
Assembly Source File  |  1990-06-14  |  22KB  |  750 lines

  1.     .386p
  2.  
  3.     PUBLIC    GSAVE
  4.     PUBLIC    nlength,CMPAGR,L_CPAG,CPAGe,CPAG2,LINE,L_SET5
  5.     PUBLIC    SET5in,CHK3,LINEND0,GSET,SKIPg,GSETe,LINEND1,PAT1
  6.     PUBLIC    PAT1j,PAT12,PAT2,PAT2j,PAT22,PAT3,L_PAT3
  7.     PUBLIC    PAT3j,PAT32,PAT4,PAT4j,PAT42,PAT5,L_PAT5,PAT5e,PAT5o
  8.     PUBLIC    PAT5j,PAT52,PATEND,LINEND,LINED2,LINTRS,HIGCMP,L_HIGC
  9.     PUBLIC    HIGCm,L_HICm,L_HICc,NONEQU,L_NOEQ,NOEQe,NOEQ1,NOEQST
  10.     PUBLIC    NOEQ2,CHGr,RECOMP,CMPe,COMPt,HIHEAD,LOWCMP
  11.     PUBLIC    L_LWC,LOWCm,L_LOWC,LOWCe,LOWCtr,LOWH1,LOWH2,CMPEND
  12.     PUBLIC    CHKLIN,CHKLOW,CHKHIG,CHKEND,TRSNON,TRSLIN,TRSin,CHKED2
  13.     PUBLIC    TRSHIG,TRSLOW
  14.     
  15. param    struc
  16.  
  17. point    dd    ?    ;データ格納ポインタ
  18. linbuf    dd    ?,?
  19. ngc    dd    ?    ;捨てられたデータの数を示すカウンタ
  20. ;
  21.     dd    ?    ;使用禁止
  22. nrefer    dd    ?     ;参照できるライン数
  23. lngth    dd    ?     ;1ラインのバイト数
  24. data    dd    ?     ;圧縮元データ格納アドレス
  25. refer    dd    ?     ;参照データ格納アドレス
  26. outd    dd    ?     ;出力データ格納アドレス
  27. work    dd    ?    ;ワークエリア先頭アドレス
  28. bml    dd    ?    ;ビットマップ長
  29. trsbuf    dd    ?    ;圧縮後に登録する参照バッファ
  30. dflag    dd    ?    ;デバッグパラメータ
  31. param    ends
  32.  
  33.  
  34. nlength    EQU    1024    ;1ラインの最大長(参照データ1ライン分のデータ長も兼ねる)
  35. wlength    EQU    1536    ;ワークエリアの1モード分の長さ
  36. worklng    EQU    4*4
  37. dbf    EQU    0
  38.  
  39. ;    MACRO
  40. debug    macro    val
  41.     pushf
  42.     push    eax
  43.     push    edx
  44.     mov    eax,val
  45.     and    eax,4fh
  46.     mov    edx,04ech    ;Volume Meter
  47.     out    dx,al
  48.     pop    edx
  49.     pop    eax
  50.     popf
  51.     endm
  52.  
  53. debugs    macro    val,val2
  54.     pushf
  55.     push    eax
  56.     push    edx
  57.     mov    eax,val
  58.     shl    eax,val2
  59.     and    eax,4fh
  60.     mov    edx,04ech    ;Volume Meter
  61.     out    dx,al
  62.     pop    edx
  63.     pop    eax
  64.     popf
  65.     endm
  66.  
  67. debugl    macro    val,val2
  68.     pushf
  69.     push    eax
  70.     push    edx
  71.     mov    eax,val
  72.     and    eax,4fh
  73.     mov    edx,04ech    ;Volume Meter
  74.     out    dx,al
  75.     mov    eax,val2
  76.     out    dx,al
  77.     pop    edx
  78.     pop    eax
  79.     popf
  80.     endm
  81.  
  82. dbret    macro
  83.     add    esp,worklng
  84.     mov    eax,0fffffffh
  85.     ret
  86.     endm
  87.     
  88. djmp    macro    val,val2
  89.     if     dbf
  90.     cmp    dword PTR dflag[ebp],val
  91.     je    val2
  92.     endif
  93.     endm
  94.     
  95. CODE    segment dword public ER use32 'CODE'
  96.     assume cs:CODE, ds:CODE
  97.     
  98. ;    Graphics Data Compress Routine for F-BASIC386
  99.  
  100. EXEC    proc    near
  101. GSAVE:    sub    esp,worklng        ;ワークエリア確保
  102.     cld            ;自動増加を指定
  103.     mov    ebp,esp        ;パラメータ用にespの値をebpに転送
  104. ;    ;完全一致モード
  105. CMPAGR:    mov    ebx,nrefer[ebp]    ;参照できるライン数を読み込む
  106.     cmp    ebx,0        ;それは0か
  107.     je    LINE        ;0なら1次元圧縮モードへ
  108.     dec    ebx        ;計算のため-1する
  109. ;
  110. L_CPAG:    mov    esi,refer[ebp]    ;参照データの先頭アドレスをesiにセット
  111.     mov    edi,data[ebp]    ;圧縮対象データの先頭アドレスをediにセット
  112.     mov    eax,nlength    ;1ライン分のデータ領域長を得る(最大値)
  113.     mul    ebx
  114.     add    esi,eax
  115.     mov    ecx,lngth[ebp]
  116. ;
  117. repe    cmpsb
  118.     jz    CPAGe
  119.     sub    ebx,1
  120.     jnc    L_CPAG
  121.     jmp    LINE
  122. CPAGe:    
  123.     mov    edi,outd[ebp]
  124.     mov    eax,ebx
  125.     cmp    ebx,7
  126.     ja    CPAG2
  127. ;
  128.     or    al,0C8h
  129.     mov    [edi],al
  130.     mov    eax,1
  131.     jmp    REGBUF
  132. ;
  133. CPAG2:    and    ah,7h
  134.     or    al,88h
  135.     xchg    al,ah        ;完全一致モードに適合したなら、それが一番短い        mov    [edi],ax    ;データ(つまり圧縮率が高い)になるため、以下のサ
  136.     mov    eax,2        ;ーチは行わず、呼び出し元へリターン
  137.     jmp    REGBUF
  138. ;
  139. ;
  140. LINE:            ;1次元圧縮モード
  141.     mov    ngc[ebp],dword PTR 0    ;非パターンデータのカウンタをクリア
  142.     mov    esi,data[ebp]        ;圧縮対象データのアドレスをセット
  143.     mov    edi,outd[ebp]        ;出力アドレスをセット
  144.     mov    ecx,lngth[ebp]        ;対象データの長さをセット
  145.     mov    point[ebp],edi        ;比較のための値をセット(非圧縮時の長さ)
  146.     add    point[ebp],ecx
  147. ;
  148. L_SET5:    ;非パターンデータバッファに対象ポイントの先頭から5バイトを転送
  149.     mov    eax,[esi]
  150.     mov    linbuf[ebp],eax
  151.     mov    bl,[esi+4]
  152.     mov    byte PTR linbuf+4[ebp],bl
  153. ;
  154.     cmp    ecx,5        ;対象データの残りが5バイト以上あるか?
  155.     jbe    CHK2        ;なければ分岐
  156. SET5in:
  157.     mov    eax,[esi]
  158.     xor    eax,[esi+1]    ;対象の5バイトはすべて同じバイトデータか
  159.     jz    PAT1        ;同じなら1パターン圧縮を行う
  160. ;
  161. CHK2:    mov    ax,[esi]
  162.     cmp    ax,[esi+2]    ;5バイト中の先頭2バイトと次の2バイトが同じか
  163.     jne    CHK5        ;違うなら5バイトパターンチェックへ
  164.     cmp    ah,al        ;先頭1バイトと次のバイトが同じか
  165.     jne    PAT2        ;違うなら2バイト圧縮を行う
  166.     jmp    PAT1        ;同じなら1パターン圧縮を行う
  167. ;
  168. CHK5:    cmp    ecx,5        ;対象データの残りが5バイト以上あるか?
  169.     jbe    LSTCHK        ;なければ分岐
  170.     mov    eax,[esi]
  171.     xor    eax,[esi+5]    ;現在の5バイトと次の5バイトが同じか
  172.     jnz    CHK3        ;違うなら3バイトパターンチェックへ
  173.     mov    bl,[esi+4]
  174.     xor    bl,[esi+9]
  175.     jz    PAT5        ;同じなら5パターン圧縮を行う
  176. ;
  177. CHK3:    mov    eax,[esi]
  178.     xor    eax,[esi+3]
  179.     and    eax,0ffffffh    ;5バイト中の先頭3バイトと次の3バイトが同じか
  180.     jz    PAT3        ;同じなら3パターン圧縮を行う
  181. ;
  182.     mov    eax,[esi]
  183.     xor    eax,[esi+4]    ;5バイト中の先頭4バイトと次の4バイトが同じか
  184.     jz    PAT4        ;同じなら4パターン圧縮を行う
  185. ;
  186. LSTCHK:    mov    ax,[esi]    ;5バイト中の先頭バイトと次のバイトと
  187.     cmp    al,ah        ;その次のバイトが同じなら1パターン圧縮を行う
  188.     jne    CHK5BT
  189.     xor    al,[esi+2]
  190.     jz    PAT1
  191.     
  192. CHK5BT:    cmp    ecx,5        ;対象データの残りが5バイト以上あるか?
  193.     jbe    LINEND1        ;なければ分岐
  194. ;
  195. NXTCHK:    inc    byte PTR ngc[ebp] ;非パターンデータカウンタをインクリメントする
  196.     add    esi,1        ;ポインタをインクリメントする
  197.     dec    ecx        ;データ数をデクリメントする
  198.     jz    LINEND0        ;0になったら分岐
  199.     cmp    byte PTR ngc[ebp],5    ;5バイト溜まったかチェック
  200.     jb    SET5in        ;溜まっていなければループ
  201. ;
  202. LINEND0:
  203.     call    GSET    ;非パターンデータを(あれば)セット
  204.     jmp    PATEND    ;ジャンプ
  205. ;
  206. GSET:    push    ecx        ;ecxを保存
  207.     mov    ecx,ngc[ebp]    ;非パターンデータ数をセット
  208.     cmp    ecx,0        ;もし非パターンデータがなければ
  209.     je    GSETe        ;分岐(リターン)
  210.     cmp    ecx,5        ;データ数は5未満か
  211.     jb    SKIPg        ;未満なら分岐
  212.     mov    ecx,5        ;以上なら念のため5をセット
  213. SKIPg:    
  214.     mov    ax,cx        ;データ数をaxにコピー
  215.     shl    al,5        ;ブロックヘッダにデータ数をセットするためシフト
  216.     or    al,11h        ;ヘッダ生成
  217.     stosb            ;ブロックヘッダストア
  218.     push    esi        ;esiを保存
  219.     lea    esi,linbuf[ebp]    ;非パターンデータの格納アドレスをセット
  220. rep    movsb            ;データ転送
  221.     mov    dword PTR ngc[ebp],0    ;カウンタをクリア
  222.     pop    esi        ;データ復帰
  223. GSETe:    pop    ecx        ;データ復帰
  224.     ret
  225. ;
  226. LINEND1:    ;残りデータが5バイト未満の時はここにくる
  227.     mov    ngc[ebp],ecx    ;非パターンカウンタに値をセット
  228.     mov    ecx,0        ;ecxを補正する
  229.     jmp    LINEND0        ;ジャンプ
  230. ;
  231. ;    1バイトパターンモード
  232. PAT1:    call    GSET    ;非パターンデータをクリアする
  233.     mov    edx,ecx    ;ブロック数計算のためecxの内容をedxに保存しておく
  234.     lodsb        ;パターンデータを読み込む
  235.     dec    ecx    ;カウンタ補正
  236.     push    edi    ;保存
  237.     mov    edi,esi    ;ディストネーションアドレスセット
  238. repe    scasb        ;違うデータが現れるまでサーチ
  239.     jz    PAT1j    ;カウントエンドでループアウトなら分岐
  240.     inc    ecx    ;カウンタ補正
  241.     sub    edi,1    ;次のサーチアドレスをセットしておく
  242. PAT1j:    mov    esi,edi
  243.     pop    edi    ;復帰
  244.     sub    edx,ecx    ;ブロック数計算
  245.     cmp    edx,15    ;ブロック数が15以上か
  246.     ja    PAT12    ;以上なら2バイトヘッダモードに分岐
  247.     mov    ah,dl    ;ブロック数をahにセット(alにはブロックデータが格納済)
  248.     or    ah,30h    ;ヘッダ生成
  249.     xchg    al,ah    ;ahを先にストアするために上下位交換
  250.     stosw        ;データストア
  251.     jmp    PATEND    ;ジャンプ
  252. PAT12:    mov    [edi+2],al    ;先にブロックデータをストア
  253.     or    dx,2000h    ;ヘッダ生成
  254.     xchg    dl,dh        ;dhを先にストアするため上下位交換
  255.     mov    [edi],dx    ;ヘッダストア
  256.     add    edi,3        ;ポインタ補正
  257.     jmp    PATEND        ;ジャンプ
  258. ;
  259. PAT2:    call    GSET
  260.     mov    ebx,ecx    ;ループエンド時のカウンタ復帰の為にecxをebxにコピー
  261.     and    ebx,1    ;mod 2
  262.     shr    ecx,1    ;\ 2  ループ回数計算
  263.     mov    edx,ecx    ;ブロック数計算のためecxの内容をedxに保存しておく
  264.     lodsw        ;パターンデータを読み込む
  265.     dec    ecx    ;カウンタ補正
  266.     push    edi    ;保存
  267.     mov    edi,esi    ;アドレスセット
  268. repe    scasw        ;違うデータが出てくるまでサーチ
  269.     jz    PAT2j    ;カウントエンドでループアウトなら分岐
  270.     inc    ecx    ;カウンタ補正
  271.     sub    edi,2    ;サーチアドレスセット
  272. PAT2j:    mov    esi,edi
  273.     pop    edi    ;復帰
  274.     sub    edx,ecx    ;ブロック数計算
  275.     shl    ecx,1    ;カウンタをバイト長に直す
  276.     or    ecx,ebx    ;復帰
  277.     cmp    edx,15    ;ブロック数は15以上か
  278.     ja    PAT22    ;以上なら分岐
  279.     or    dl,50h    ;ヘッダ生成
  280.     mov    [edi],dl;ヘッダストア
  281.     inc    edi    ;ポインタ補正
  282.     stosw        ;データストア
  283.     jmp    PATEND    ;ジャンプ
  284. PAT22:    mov    [edi+2],ax    ;データストア
  285.     or    dx,4000h    ;ヘッダ生成
  286.     xchg    dl,dh        ;上下位交換
  287.     mov    [edi],dx    ;ヘッダストア
  288.     add    edi,4        ;ポインタ補正
  289.     jmp    PATEND        ;ジャンプ
  290. ;
  291. PAT3:    call    GSET
  292.     mov    ebx,3    ;残りデータ長を3で割る
  293.     xor    edx,edx
  294.     mov    eax,ecx
  295.     div    bx    ;商:ax 余り:dx
  296.     mov    ebx,edx    ;最後のecx補正のため余りをebxに保存しておく
  297.     mov    ecx,eax    ;商をカウンタに転送
  298.     push    ecx    ;ブロック数計算のためecxの内容を保存しておく
  299.     lodsd        ;パターンデータを読み込む
  300.     dec    ecx    ;カウンタ補正
  301.     and    eax,0ffffffh    ;4バイト目をマスク
  302.     mov    edx,eax    ;転送
  303.     dec    esi    ;ポインタ補正
  304. L_PAT3:    lodsd        ;4バイト読み込む
  305.     dec    esi    ;3バイトだけ読んだことにするためポインタを補正する
  306.     and    eax,0ffffffh    ;4バイト目をマスク
  307.     cmp    eax,edx    ;比較
  308.     jnz    PAT3j    ;違ったらループアウト
  309.     loop    L_PAT3    ;ループチェック
  310.     jmp    PAT3j2
  311. PAT3j:    sub    esi,3    ;ポインタ補正
  312. PAT3j2:    mov    eax,edx    ;データ転送
  313.     pop    edx    ;ecx(Stack)->edx
  314.     sub    edx,ecx    ;ブロック数計算
  315.     lea    ecx,[ecx][ecx*2] ;ecx=ecx*3
  316.     add    ecx,ebx    ;残りデータ長を復活
  317.     cmp    edx,15    ;ブロック数は15を越えているか
  318.     ja    PAT32    ;上なら2バイトヘッダモードへ
  319.     or    dl,70h    ;ヘッダ生成
  320.     shl    eax,8    ;ヘッダのスペースをアキュムレータ上に空ける
  321.     mov    al,dl    ;ヘッダをアキュムレータにストア
  322.     stosd        ;データストア
  323.     jmp    PATEND    ;ジャンプ
  324. PAT32:    mov    [edi+2],eax ;データストア
  325.     or    dx,6000h ;ヘッダ生成
  326.     xchg    dl,dh    ;上下交換
  327.     mov    [edi],dx ;ヘッダストア
  328.     add    edi,5    ;ポインタ補正
  329.     jmp    PATEND    ;ジャンプ
  330. ;
  331. PAT4:    call    GSET
  332.     mov    ebx,ecx
  333.     and    ebx,3
  334.     shr    ecx,2
  335.     mov    edx,ecx    ;ブロック数計算のためecxの内容をedxに保存しておく
  336.     lodsd        ;パターンデータを読み込む
  337.     dec    ecx    ;カウンタ補正
  338.     push    edi
  339.     mov    edi,esi
  340. repe    scasd
  341.     jz    PAT4j    ;カウントエンドでループアウトなら分岐
  342.     inc    ecx    ;カウンタ補正
  343.     sub    edi,4
  344. PAT4j:    mov    esi,edi
  345.     pop    edi
  346.     sub    edx,ecx    ;ブロック数計算
  347.     shl    ecx,2
  348.     add    ecx,ebx
  349.     cmp    edx,15
  350.     ja    PAT42
  351.     or    dl,90h
  352.     mov    [edi],dl
  353.     inc    edi
  354.     stosd        ;データストア
  355.     jmp    PATEND
  356. PAT42:    mov    [edi+2],eax
  357.     or    dx,8000h
  358.     xchg    dl,dh
  359.     mov    [edi],dx
  360.     add    edi,6
  361.     jmp    PATEND
  362. ;
  363. PAT5:    call    GSET
  364.     mov    ebx,5    ;残りデータ長を5で割る
  365.     xor    edx,edx
  366.     mov    eax,ecx
  367.     div    bx
  368.     push    edx    ;最後のecx補正のため余りを保存しておく
  369.     mov    ecx,eax    ;商をカウンタに転送
  370.     mov    edx,ecx    ;ブロック数計算のためecxの内容を保存しておく
  371.     lodsb        ;最初の1バイトのパターンデータを読み込む
  372.     mov    bl,al    ;blに転送
  373.     lodsd        ;後の4バイトを読み込む
  374.     dec    ecx    ;カウンタ補正
  375.     push    edi    ;保存
  376.     mov    edi,esi    ;アドレスセット
  377. L_PAT5:    inc    edi    ;最初の1バイトの比較
  378.     cmp    bl,[edi-1]
  379.     jnz    PAT5o    ;違えばループアウト
  380.     scasd        ;次の4バイトの比較
  381.     jnz    PAT5e    ;違えばループアウト
  382.     loop    L_PAT5    ;ループチェック
  383.     jmp    PAT5j
  384. PAT5e:    sub    edi,4    ;ポインタ補正
  385. PAT5o:    sub    edi,1    ;ポインタ補正
  386. PAT5j:    mov    esi,edi
  387.     pop    edi    ;復帰
  388.     sub    edx,ecx    ;ブロック数計算
  389.     lea    ecx,[ecx][ecx*4] ;ecx=ecx*5
  390.     cmp    edx,15    ;ブロック数は15を越えたか
  391.     ja    PAT52    ;上なら2バイトヘッダモードへ
  392.     or    dl,0B0h    ;ヘッダ生成
  393.     mov    dh,bl    ;データを転送
  394.     mov    [edi],dx ;データストア
  395.     add    edi,2    ;ポインタ補正
  396.     stosd        ;データストア
  397.     pop    ebx    ;edx(Stack)->ebx
  398.     add    ecx,ebx    ;残りデータ長計算
  399.     jmp    PATEND    ;ジャンプ
  400. PAT52:    mov    [edi+2],bl ;データストア
  401.     mov    [edi+3],eax ;データストア
  402.     or    dx,0A000h ;ヘッダ生成
  403.     xchg    dl,dh    ;上下交換
  404.     mov    [edi],dx ;ヘッダストア
  405.     add    edi,7    ;ポインタ補正
  406.     pop    ebx    ;edx(Stack)->ebx
  407.     add    ecx,ebx    ;残りデータ長計算
  408. ;
  409. PATEND:    cmp    point[ebp],edi    ;非圧縮時より長いデータとなっていないか?
  410.     jbe    NONLINE        ;長ければモードエンド
  411.     cmp    ecx,0    ;データを全てチェックしたか
  412.     ja    L_SET5    ;まだのこっていたら分岐
  413. ;
  414. LINEND:    mov    eax,outd[ebp]    ;出力データ格納アドレスの先頭を得る
  415.     sub    edi,eax        ;ブロックデータバイト数計算
  416.     mov    eax,edi
  417.     mov    esi,outd[ebp]    ;出力データ格納アドレスの先頭をセット
  418.     mov    edi,work[ebp]    ;最後に比較するため格納しておくアドレスをセット
  419.     mov    edx,eax        ;データ数を退避しておく
  420.     stosd            ;最後の比較の為の数値をストア
  421.     inc    dword PTR [edi-4]    ;数値の補正(ヘッダの分)
  422.     cmp    eax,7        ;データ数は7以上か
  423.     ja    LINED2        ;以上なら分岐
  424. ;
  425.     or    al,0C0h        ;ヘッダ生成
  426.     stosb            ;ヘッダストア
  427.     jmp    LINTRS        ;分岐
  428. ;
  429. NONLINE:            ;圧縮データを生成出来なかったのでこのモードを
  430.     mov    work[ebp],0fffffffh ;選ばない様に、データをセットしておく
  431.     jmp    HIGCMP        ;高圧縮モードへ
  432. ;
  433. LINED2:    inc    dword PTR [edi-4] ;2バイトヘッダなので数値をインクリメント
  434.     or    ax,8000h    ;ヘッダ生成
  435.     xchg    ah,al        ;上下交換
  436.     stosw            ;ヘッダストア
  437. ;
  438. LINTRS:    mov    ecx,edx        ;退避しておいた値を復帰
  439. rep    movsb            ;データ転送
  440. ;    高圧縮モード
  441. HIGCMP:    
  442.     mov    edx,lngth[ebp]    ;現モードの比較の為にあらかじめ値を入れておく
  443.     add    edx,2
  444.     mov    ebx,work[ebp]    ;比較の為のワーク領域の先頭アドレスを得る
  445.     add    ebx,wlength*4    ;現モードのアドレスを計算
  446.     mov    [ebx],edx    ;ダミーカウンタ
  447.     mov    eax,nrefer[ebp]    ;参照できるライン数を得る
  448.     cmp    eax,0        ;0か
  449.     je    LOWCMP        ;0なら現モード終了
  450.     dec    eax        ;計算の為-1する
  451. ;
  452. L_HIGC:    mov    edi,outd[ebp]    ;出力データアドレスをセット
  453.     mov    point[ebp],edi    ;値を保存
  454.     mov    esi,data[ebp]    ;圧縮対象データアドレスをセット
  455.     mov    edi,refer[ebp]    ;参照バッファアドレスを読み込む
  456.     mov    ecx,lngth[ebp]    ;データ長を得る
  457.     mov    ngc[ebp],eax    ;参照データナンバーを保存
  458.     imul    ax,nlength    ;参照データアドレス計算
  459.     add    edi,eax
  460. ;
  461.     call    HIGCm        ;高圧縮を行う
  462. ;
  463.     mov    eax,ngc[ebp]    ;参照データナンバーを復帰
  464.     sub    eax,1        ;データナンバーをデクリメント
  465.     jnc    L_HIGC        ;マイナスになって(全て参照)いなければループ
  466.     jmp    LOWCMP        ;参照しおわったら低圧縮モードへ
  467. ;
  468. HIGCm:    push    ebx    ;データバッファアドレス保存
  469.     push    edx    ;生成データ長チェック値保存
  470. ;
  471. L_HICm:    mov    ebx,1    ;同データカウンタ(オフセットカウンタ)を初期化
  472.     xor    edx,edx    ;異データカウンタをクリア
  473. L_HICc:    cmpsb        ;1バイト比較する
  474.     jnz    NONEQU    ;違うデータなら分岐
  475.     inc    ebx    ;同じなら同データカウンタをインクリメント
  476.     loop    L_HICc    ;全てチェックしたか?していなければループ
  477.     jmp    HIEDin    ;終わっていたら終了処理へ
  478. ;
  479. NONEQU:    dec    esi    ;ポインタ補正
  480.     dec    edi    ;ポインタ補正
  481.     mov    point+4[ebp],esi    ;後のデータ転送の為ポインタを保存
  482. L_NOEQ:    cmpsb        ;1バイト比較する
  483.     jz    NOEQe    ;同じデータなら分岐
  484.     inc    edx    ;違うなら異データカウンタをインクリメント
  485.     loop    L_NOEQ    ;全てチェックしたか?していなければループ
  486. NOEQe:    dec    esi    ;ポインタ補正
  487.     dec    edi    ;ポインタ補正
  488.     xchg    edi,point[ebp]    ;出力データと参照データのアドレスを交換
  489.     xchg    esi,point+4[ebp] ;異データの先頭と現在の対象ポインタを交換
  490.     cmp    ebx,63    ;同データカウンタは63未満か
  491.     ja    NOEQ2    ;越えていたら2バイトブロックヘッダモードへ
  492.     cmp    edx,3    ;異データカウンタは3未満か
  493.     ja    NOEQ2    ;越えていたら2バイトブロックヘッダモードへ
  494. ;
  495. NOEQ1:    jne    NOEQST    ;異データカウンタが3でなければ分岐
  496.     dec    edx    ;異データカウンタをデクリメント
  497.     mov    eax,ebx    ;同データカウンタをオフセットとしてeaxにセット
  498.     or    al,80h    ;ヘッダ生成
  499.     stosb        ;ヘッダストア
  500.     movsb        ;データストア
  501.     mov    ebx,1    ;データオフセットカウンタを初期化
  502. NOEQST:    mov    eax,edx    ;異データカウンタをeaxにセット
  503.     dec    eax    ;データ2バイトフラグを作るためカウンタを-1
  504.     shl    al,6    ;データ2バイトフラグ生成
  505.     or    al,80h    ;ヘッダ生成
  506.     or    al,bl    ;データオフセットをヘッダにセット
  507.     stosb        ;ヘッダストア
  508.     push    ecx    ;転送のためecxを保存
  509.     mov    ecx,edx    ;データ数をセット
  510. rep    movsb        ;データ転送
  511.     pop    ecx    ;ecx復帰
  512.     jmp    RECOMP    ;データ長チェックへ分岐
  513. ;
  514. NOEQ2:    mov    eax,edx    ;異データカウンタをeaxにセット
  515.     xor    edx,edx    ;異データストアループためにカウンタをクリア
  516.     cmp    eax,15    ;異データカウンタは15以下か
  517.     jbe    CHGr    ;以下なら分岐
  518.     mov    edx,eax    ;異データ長セット
  519.     sub    edx,15    ;残りデータ長セット
  520.     mov    eax,15    ;取り合えず最初の15バイトをセット
  521. CHGr:    push    ecx    ;対象データカウンタ保存
  522.     mov    ecx,eax    ;転送データ長セット
  523.     shl    eax,11    ;異データ長をヘッダにセット
  524.     or    eax,ebx    ;データオフセットをヘッダにセット
  525.     mov    ebx,1    ;データオフセットを初期化
  526.     xchg    al,ah    ;上下交換
  527.     stosw        ;ヘッダストア
  528. rep    movsb        ;データ転送
  529.     pop    ecx    ;対象データカウンタ復帰
  530.     cmp    edx,0    ;異データは残っているか
  531.     jne    NOEQ2    ;残っていたらループ
  532. ;
  533. RECOMP:    xchg    edi,point[ebp]    ;出力データと参照データのアドレスを交換
  534.     xchg    esi,point+4[ebp] ;異データの先頭と現在の対象ポインタを交換
  535.     cmp    ecx,0        ;まだ圧縮していないデータは残っているか
  536.     jne    L_HICm        ;残っていたらループ
  537. ;
  538. HIEDin:    xchg    edi,point[ebp]    ;出力データと参照データのアドレスを交換
  539.     sub    edi,outd[ebp]    ;圧縮データ長計算
  540.     pop    edx        ;生成データ長復帰
  541.     cmp    edi,edx        ;今までの値より今圧縮した方が短いか
  542.     jb    COMPt        ;短ければワークエリアに転送
  543. CMPe:    pop    ebx        ;長ければebxを復帰して
  544.     ret            ;リターン
  545. ;
  546. COMPt:    mov    edx,edi        ;生成データ長を新しいものに交換
  547.     mov    esi,outd[ebp]    ;転送元アドレスセット
  548.     pop    ebx        ;転送先アドレスを復帰
  549.     mov    edi,ebx        ;転送先アドレスをセット
  550.     mov    ecx,edx        ;転送データ長セット
  551.     mov    eax,edx        ;比較データ長セット
  552.     add    eax,2        ;ヘッダ長を足す
  553.     stosd            ;比較データ長ストア
  554.     mov    eax,ngc[ebp]    ;参照ラインナンバーを得る
  555.     or    al,0D0h        ;ヘッダ生成
  556.     stosb            ;トップヘッダストア
  557.     mov    eax,ecx        ;ヘッダにデータ長をセット
  558.     cmp    eax,127        ;127バイトを越えたか
  559.     jbe    HIHEAD        ;越えていなければ分岐
  560.     inc    dword PTR [edi-5] ;越えていれば比較データ長をインクリメント
  561.     xchg    ah,al        ;上下交換
  562.     stosw            ;データカウンタヘッダストア
  563. rep    movsb            ;バッファにデータを転送する
  564.     ret
  565. HIHEAD:    or    al,80h        ;ヘッダ生成
  566.     stosb            ;ヘッダストア
  567. rep    movsb            ;バッファにデータを転送する
  568.     ret
  569. ;
  570. ;    低圧縮モード
  571. LOWCMP:
  572.     mov    edi,work[ebp]    ;比較のための保存アドレス計算
  573.     add    edi,wlength*2
  574.     mov    eax,0ffffffffh    ;圧縮後のデータ長とヘッダをダミーで埋める
  575.     stosd            ;ダミーカウンタ
  576.     stosb            ;ダミートップヘッダ
  577.     mov    eax,nrefer[ebp]    ;参照できるライン数を得る
  578.     cmp    eax,0        ;0か
  579.     je    CMPEND        ;0なら分岐
  580.     mov    ebx,bml[ebp]    ;ビットマップ長を読み込む
  581.     add    ebx,outd[ebp]    ;データ格納領域先頭アドレス計算
  582.     dec    eax        ;計算のため参照ラインナンバーを-1する
  583.     mov    edx,lngth[ebp]    ;現モードの比較の為にあらかじめ値を入れておく
  584.     add    edx,2
  585. ;
  586. L_LWC:
  587.     push    eax        ;参照ラインナンバー保存
  588.     push    edx        ;mulにより下位16ビットが壊されるので保存
  589.     mov    esi,data[ebp]    ;対象データ格納アドレスセット
  590.     mov    edi,refer[ebp]    ;参照データ格納アドレス計算
  591.     mov    ecx,nlength    
  592.     mul    ecx
  593.     add    edi,eax        ;参照データ格納アドレスセット
  594.     pop    edx        ;復帰
  595. ;
  596.     call    LOWCm        ;低圧縮を行う
  597. ;
  598.     pop    eax        ;復帰
  599.     sub    eax,1        ;データナンバーをデクリメント
  600.     jnc    L_LWC        ;-1になって(全て参照)いなければループ
  601.     jmp    CMPEND        ;参照しおわったら最終比較へ
  602. ;
  603. LOWCm:    xor    eax,eax    ;ビットマップをクリアするためにeaxを0にする
  604.     push    edi    ;参照データ格納アドレス保存
  605.     mov    edi,outd[ebp]
  606.     mov    ecx,bml[ebp]    ;ビットマップ長セット
  607. rep    stosb        ;ビットマップクリア
  608.     pop    edi    ;復帰
  609.     mov    ecx,lngth[ebp]    ;データ長セット
  610. ;
  611.     push    ebx    ;データ格納アドレス保存
  612.     push    edx    ;生成データ長チェック値保存
  613.     push    ecx    ;データ長保存
  614.     dec    dword PTR [esp]
  615. L_LOWC:
  616. repe    cmpsb        ;異データが見つかるまで比較
  617.     jz    LOWCe    ;カウントエンドでループアウトなら分岐
  618.     mov    al,[esi-1] ;異データをロード
  619.     mov    [ebx],al ;異データをストア
  620.     inc    ebx    ;データ格納ポインタを進める
  621.     mov    edx,[esp] ;全データ長を得る
  622.     sub    edx,ecx    ;何ビット目で異データが出たか計算する
  623.     mov    eax,edx    ;それをeaxにコピー
  624.     shr    edx,3    ;8で割る    [ビットマップ先頭から何バイト目か]
  625.     and    eax,7    ;下位3ビットのみ有効    [そのバイトのどのビットか]
  626.     add    edx,outd[ebp]    ;変更ビットマップのアドレスを得る
  627.     bts    [edx],ax ;対応ビットを立てる    [ MSB:bit7  LSB:bit0 ]
  628.     cmp    ecx,0    ;全てのデータを処理したか
  629.     ja    L_LOWC    ;していなければループ
  630. ;
  631. LOWCe:    pop    ecx    ;スタック補正
  632.     sub    ebx,outd[ebp]    ;処理済データ長を計算する
  633.     pop    edx    ;生成データ長復帰
  634.     cmp    edx,ebx    ;今までの値より今圧縮した方が短いか
  635.     ja    LOWCtr    ;短ければワークエリアに転送
  636. ;
  637.     pop    ebx    ;長ければebxを復帰して
  638.     ret        ;リターン
  639. ;
  640. LOWCtr:    mov    edx,ebx        ;生成データ長を新しいものに交換
  641.     mov    eax,ebx        ;現在のデータ長をeaxにコピー
  642.     mov    ecx,ebx        ;    〃     ecxにコピー
  643.     mov    esi,outd[ebp]    ;転送元アドレスセット
  644.     mov    edi,work[ebp]    ;転送先アドレス計算
  645.     add    edi,wlength*2
  646.     add    eax,2        ;ヘッダ長(仮に2)を足す
  647.     stosd            ;カウンタストア
  648.     mov    eax,[esp+8]    ;コール前に保存した参照ラインナンバーを得る
  649.     or    al,0D8h        ;トップヘッダ生成
  650.     stosb            ;トップヘッダストア
  651.     mov    eax,ebx        ;データバイト数をeaxにセット
  652.     cmp    eax,128        ;128以上か
  653.     jae    LOWH2        ;データバイト数ヘッダ2バイトモードへ
  654.     or    al,80h        ;データバイト数ヘッダ生成
  655.     stosb            ;    〃         ストア
  656.     jmp    LOWH1        ;ジャンプ
  657. LOWH2:    inc    dword PTR [edi-5] ;データ長をインクリメント
  658.     xchg    al,ah        ;上下交換
  659.     stosw            ;データバイト数ヘッダストア
  660. LOWH1:    pop    ebx        ;ebx復帰
  661. rep    movsb            ;データ転送
  662.     ret            ;リターン
  663. ;
  664. ;
  665. CMPEND:        ;圧縮後の各データ長比較
  666.     mov    ecx,lngth[ebp]    ;非圧縮時のデータ長を得る
  667.     xor    ebx,ebx        ;圧縮種類インデックスを初期化(0)
  668.     mov    edi,work[ebp]    ;1次元圧縮モードのデータ長格納アドレスを得る
  669. ;
  670. CHKLIN:    
  671.     inc    ecx        ;非圧縮時のデータ長にヘッダ長を加える
  672.     cmp    ecx,[edi]    ;非圧縮時と1次元圧縮時のデータ長を加える
  673.     jbe    CHKLOW        ;非圧縮時の方が小さいか等しければ次の比較へ
  674.     mov    ebx,1        ;大きければインデックスを1次元圧縮モードに
  675.     mov    ecx,[edi]    ;データ長を1次元圧縮モードに
  676. CHKLOW:    
  677.     cmp    ecx,[edi+wlength*2] ;チェックしたデータ長と低圧縮モードを比べる
  678.     jbe    CHKHIG        ;低圧縮モードの方が大きければ分岐
  679.     mov    ebx,2        ;小さければインデックスを低圧縮モードに
  680.     mov    ecx,[edi+wlength*2] ;データ長を低圧縮モードに
  681. CHKHIG:    
  682.     cmp    ecx,[edi+wlength*4] ;チェックしたデータ長と高圧縮モードを比べる
  683.     jbe    CHKEND        ;高圧縮モードの方が大きければ分岐
  684.     mov    ebx,3        ;インデックスを高圧縮モードに
  685.     mov    ecx,[edi+wlength*4] ;データ長を高圧縮モードに
  686. CHKEND:    
  687.     mov    edi,outd[ebp]    ;出力データ格納アドレスをセット
  688.     cmp    ebx,2        ;インデックスは2より小さいか
  689.     jae    CHKED2        ;小さくなければ分岐
  690.     cmp    ebx,0        ;インデックスは0より大きいか
  691.     ja    TRSLIN        ;大きければ1次元圧縮データを転送
  692. ;                ;大きくなければ非圧縮データを転送
  693. TRSNON:    
  694.     dec    ecx        ;ヘッダの分のデータ長を引く
  695.     mov    al,40h        ;ヘッダ生成
  696.     stosb            ;ヘッダストア
  697.     mov    esi,data[ebp]    ;非圧縮データの格納アドレスを得る
  698. rep    movsb            ;転送
  699.     mov    eax,lngth[ebp]    ;本プログラム呼出元に返す値をセット
  700.     inc    eax        ;ヘッダ長を加える
  701.     jmp    REGBUF
  702. ;    1次元圧縮データ転送
  703. TRSLIN:    
  704.     mov    esi,work[ebp]    ;1次元圧縮データの格納アドレスを得る
  705. TRSin:    lodsd            ;データ長を得る
  706.     mov    edx,eax        ;呼出元へ渡すためにedxに保存しておく
  707. rep    movsb            ;転送
  708.     mov    eax,edx        ;呼出元に返す値を復帰
  709. ;
  710. REGBUF:    push    eax
  711.     mov    esi,data[ebp]    ;参照バッファを新たに登録しなおす
  712.     mov    eax,trsbuf[ebp]
  713.     mov    edi,nlength
  714.     xor    edx,edx
  715.     mul    edi
  716.     add    eax,refer[ebp]
  717.     mov    edi,eax
  718.     mov    ecx,lngth[ebp]
  719.     mov    edx,ecx
  720.     and    edx,3
  721.     mov    eax,[esi]
  722.     mov    [edi],eax
  723.     add    edi,edx
  724.     add    esi,edx
  725.     shr    ecx,2
  726. rep    movsd
  727.     pop    eax
  728. ;
  729.     add    esp,worklng    ;ワークエリア解放
  730.     ret            ;呼出元へリターン
  731. ;
  732. CHKED2:    je    TRSLOW
  733. ;
  734. TRSHIG:    
  735.     mov    esi,work[ebp]
  736.     add    esi,wlength*4
  737.     jmp    TRSin
  738. ;
  739. TRSLOW:    
  740.     mov    esi,work[ebp]
  741.     add    esi,wlength*2
  742.     jmp    TRSin
  743. ;
  744. ;
  745. ;
  746. EXEC    endp
  747. CODE    ends
  748.     end
  749.  
  750.