home *** CD-ROM | disk | FTP | other *** search
- .386p
-
- PUBLIC GSAVE
- PUBLIC nlength,CMPAGR,L_CPAG,CPAGe,CPAG2,LINE,L_SET5
- PUBLIC SET5in,CHK3,LINEND0,GSET,SKIPg,GSETe,LINEND1,PAT1
- PUBLIC PAT1j,PAT12,PAT2,PAT2j,PAT22,PAT3,L_PAT3
- PUBLIC PAT3j,PAT32,PAT4,PAT4j,PAT42,PAT5,L_PAT5,PAT5e,PAT5o
- PUBLIC PAT5j,PAT52,PATEND,LINEND,LINED2,LINTRS,HIGCMP,L_HIGC
- PUBLIC HIGCm,L_HICm,L_HICc,NONEQU,L_NOEQ,NOEQe,NOEQ1,NOEQST
- PUBLIC NOEQ2,CHGr,RECOMP,CMPe,COMPt,HIHEAD,LOWCMP
- PUBLIC L_LWC,LOWCm,L_LOWC,LOWCe,LOWCtr,LOWH1,LOWH2,CMPEND
- PUBLIC CHKLIN,CHKLOW,CHKHIG,CHKEND,TRSNON,TRSLIN,TRSin,CHKED2
- PUBLIC TRSHIG,TRSLOW
-
- param struc
-
- point dd ? ;データ格納ポインタ
- linbuf dd ?,?
- ngc dd ? ;捨てられたデータの数を示すカウンタ
- ;
- dd ? ;使用禁止
- nrefer dd ? ;参照できるライン数
- lngth dd ? ;1ラインのバイト数
- data dd ? ;圧縮元データ格納アドレス
- refer dd ? ;参照データ格納アドレス
- outd dd ? ;出力データ格納アドレス
- work dd ? ;ワークエリア先頭アドレス
- bml dd ? ;ビットマップ長
- trsbuf dd ? ;圧縮後に登録する参照バッファ
- dflag dd ? ;デバッグパラメータ
- param ends
-
-
- nlength EQU 1024 ;1ラインの最大長(参照データ1ライン分のデータ長も兼ねる)
- wlength EQU 1536 ;ワークエリアの1モード分の長さ
- worklng EQU 4*4
- dbf EQU 0
-
- ; MACRO
- debug macro val
- pushf
- push eax
- push edx
- mov eax,val
- and eax,4fh
- mov edx,04ech ;Volume Meter
- out dx,al
- pop edx
- pop eax
- popf
- endm
-
- debugs macro val,val2
- pushf
- push eax
- push edx
- mov eax,val
- shl eax,val2
- and eax,4fh
- mov edx,04ech ;Volume Meter
- out dx,al
- pop edx
- pop eax
- popf
- endm
-
- debugl macro val,val2
- pushf
- push eax
- push edx
- mov eax,val
- and eax,4fh
- mov edx,04ech ;Volume Meter
- out dx,al
- mov eax,val2
- out dx,al
- pop edx
- pop eax
- popf
- endm
-
- dbret macro
- add esp,worklng
- mov eax,0fffffffh
- ret
- endm
-
- djmp macro val,val2
- if dbf
- cmp dword PTR dflag[ebp],val
- je val2
- endif
- endm
-
- CODE segment dword public ER use32 'CODE'
- assume cs:CODE, ds:CODE
-
- ; Graphics Data Compress Routine for F-BASIC386
-
- EXEC proc near
- GSAVE: sub esp,worklng ;ワークエリア確保
- cld ;自動増加を指定
- mov ebp,esp ;パラメータ用にespの値をebpに転送
- ; ;完全一致モード
- CMPAGR: mov ebx,nrefer[ebp] ;参照できるライン数を読み込む
- cmp ebx,0 ;それは0か
- je LINE ;0なら1次元圧縮モードへ
- dec ebx ;計算のため-1する
- ;
- L_CPAG: mov esi,refer[ebp] ;参照データの先頭アドレスをesiにセット
- mov edi,data[ebp] ;圧縮対象データの先頭アドレスをediにセット
- mov eax,nlength ;1ライン分のデータ領域長を得る(最大値)
- mul ebx
- add esi,eax
- mov ecx,lngth[ebp]
- ;
- repe cmpsb
- jz CPAGe
- sub ebx,1
- jnc L_CPAG
- jmp LINE
- CPAGe:
- mov edi,outd[ebp]
- mov eax,ebx
- cmp ebx,7
- ja CPAG2
- ;
- or al,0C8h
- mov [edi],al
- mov eax,1
- jmp REGBUF
- ;
- CPAG2: and ah,7h
- or al,88h
- xchg al,ah ;完全一致モードに適合したなら、それが一番短い mov [edi],ax ;データ(つまり圧縮率が高い)になるため、以下のサ
- mov eax,2 ;ーチは行わず、呼び出し元へリターン
- jmp REGBUF
- ;
- ;
- LINE: ;1次元圧縮モード
- mov ngc[ebp],dword PTR 0 ;非パターンデータのカウンタをクリア
- mov esi,data[ebp] ;圧縮対象データのアドレスをセット
- mov edi,outd[ebp] ;出力アドレスをセット
- mov ecx,lngth[ebp] ;対象データの長さをセット
- mov point[ebp],edi ;比較のための値をセット(非圧縮時の長さ)
- add point[ebp],ecx
- ;
- L_SET5: ;非パターンデータバッファに対象ポイントの先頭から5バイトを転送
- mov eax,[esi]
- mov linbuf[ebp],eax
- mov bl,[esi+4]
- mov byte PTR linbuf+4[ebp],bl
- ;
- cmp ecx,5 ;対象データの残りが5バイト以上あるか?
- jbe CHK2 ;なければ分岐
- SET5in:
- mov eax,[esi]
- xor eax,[esi+1] ;対象の5バイトはすべて同じバイトデータか
- jz PAT1 ;同じなら1パターン圧縮を行う
- ;
- CHK2: mov ax,[esi]
- cmp ax,[esi+2] ;5バイト中の先頭2バイトと次の2バイトが同じか
- jne CHK5 ;違うなら5バイトパターンチェックへ
- cmp ah,al ;先頭1バイトと次のバイトが同じか
- jne PAT2 ;違うなら2バイト圧縮を行う
- jmp PAT1 ;同じなら1パターン圧縮を行う
- ;
- CHK5: cmp ecx,5 ;対象データの残りが5バイト以上あるか?
- jbe LSTCHK ;なければ分岐
- mov eax,[esi]
- xor eax,[esi+5] ;現在の5バイトと次の5バイトが同じか
- jnz CHK3 ;違うなら3バイトパターンチェックへ
- mov bl,[esi+4]
- xor bl,[esi+9]
- jz PAT5 ;同じなら5パターン圧縮を行う
- ;
- CHK3: mov eax,[esi]
- xor eax,[esi+3]
- and eax,0ffffffh ;5バイト中の先頭3バイトと次の3バイトが同じか
- jz PAT3 ;同じなら3パターン圧縮を行う
- ;
- mov eax,[esi]
- xor eax,[esi+4] ;5バイト中の先頭4バイトと次の4バイトが同じか
- jz PAT4 ;同じなら4パターン圧縮を行う
- ;
- LSTCHK: mov ax,[esi] ;5バイト中の先頭バイトと次のバイトと
- cmp al,ah ;その次のバイトが同じなら1パターン圧縮を行う
- jne CHK5BT
- xor al,[esi+2]
- jz PAT1
-
- CHK5BT: cmp ecx,5 ;対象データの残りが5バイト以上あるか?
- jbe LINEND1 ;なければ分岐
- ;
- NXTCHK: inc byte PTR ngc[ebp] ;非パターンデータカウンタをインクリメントする
- add esi,1 ;ポインタをインクリメントする
- dec ecx ;データ数をデクリメントする
- jz LINEND0 ;0になったら分岐
- cmp byte PTR ngc[ebp],5 ;5バイト溜まったかチェック
- jb SET5in ;溜まっていなければループ
- ;
- LINEND0:
- call GSET ;非パターンデータを(あれば)セット
- jmp PATEND ;ジャンプ
- ;
- GSET: push ecx ;ecxを保存
- mov ecx,ngc[ebp] ;非パターンデータ数をセット
- cmp ecx,0 ;もし非パターンデータがなければ
- je GSETe ;分岐(リターン)
- cmp ecx,5 ;データ数は5未満か
- jb SKIPg ;未満なら分岐
- mov ecx,5 ;以上なら念のため5をセット
- SKIPg:
- mov ax,cx ;データ数をaxにコピー
- shl al,5 ;ブロックヘッダにデータ数をセットするためシフト
- or al,11h ;ヘッダ生成
- stosb ;ブロックヘッダストア
- push esi ;esiを保存
- lea esi,linbuf[ebp] ;非パターンデータの格納アドレスをセット
- rep movsb ;データ転送
- mov dword PTR ngc[ebp],0 ;カウンタをクリア
- pop esi ;データ復帰
- GSETe: pop ecx ;データ復帰
- ret
- ;
- LINEND1: ;残りデータが5バイト未満の時はここにくる
- mov ngc[ebp],ecx ;非パターンカウンタに値をセット
- mov ecx,0 ;ecxを補正する
- jmp LINEND0 ;ジャンプ
- ;
- ; 1バイトパターンモード
- PAT1: call GSET ;非パターンデータをクリアする
- mov edx,ecx ;ブロック数計算のためecxの内容をedxに保存しておく
- lodsb ;パターンデータを読み込む
- dec ecx ;カウンタ補正
- push edi ;保存
- mov edi,esi ;ディストネーションアドレスセット
- repe scasb ;違うデータが現れるまでサーチ
- jz PAT1j ;カウントエンドでループアウトなら分岐
- inc ecx ;カウンタ補正
- sub edi,1 ;次のサーチアドレスをセットしておく
- PAT1j: mov esi,edi
- pop edi ;復帰
- sub edx,ecx ;ブロック数計算
- cmp edx,15 ;ブロック数が15以上か
- ja PAT12 ;以上なら2バイトヘッダモードに分岐
- mov ah,dl ;ブロック数をahにセット(alにはブロックデータが格納済)
- or ah,30h ;ヘッダ生成
- xchg al,ah ;ahを先にストアするために上下位交換
- stosw ;データストア
- jmp PATEND ;ジャンプ
- PAT12: mov [edi+2],al ;先にブロックデータをストア
- or dx,2000h ;ヘッダ生成
- xchg dl,dh ;dhを先にストアするため上下位交換
- mov [edi],dx ;ヘッダストア
- add edi,3 ;ポインタ補正
- jmp PATEND ;ジャンプ
- ;
- PAT2: call GSET
- mov ebx,ecx ;ループエンド時のカウンタ復帰の為にecxをebxにコピー
- and ebx,1 ;mod 2
- shr ecx,1 ;\ 2 ループ回数計算
- mov edx,ecx ;ブロック数計算のためecxの内容をedxに保存しておく
- lodsw ;パターンデータを読み込む
- dec ecx ;カウンタ補正
- push edi ;保存
- mov edi,esi ;アドレスセット
- repe scasw ;違うデータが出てくるまでサーチ
- jz PAT2j ;カウントエンドでループアウトなら分岐
- inc ecx ;カウンタ補正
- sub edi,2 ;サーチアドレスセット
- PAT2j: mov esi,edi
- pop edi ;復帰
- sub edx,ecx ;ブロック数計算
- shl ecx,1 ;カウンタをバイト長に直す
- or ecx,ebx ;復帰
- cmp edx,15 ;ブロック数は15以上か
- ja PAT22 ;以上なら分岐
- or dl,50h ;ヘッダ生成
- mov [edi],dl;ヘッダストア
- inc edi ;ポインタ補正
- stosw ;データストア
- jmp PATEND ;ジャンプ
- PAT22: mov [edi+2],ax ;データストア
- or dx,4000h ;ヘッダ生成
- xchg dl,dh ;上下位交換
- mov [edi],dx ;ヘッダストア
- add edi,4 ;ポインタ補正
- jmp PATEND ;ジャンプ
- ;
- PAT3: call GSET
- mov ebx,3 ;残りデータ長を3で割る
- xor edx,edx
- mov eax,ecx
- div bx ;商:ax 余り:dx
- mov ebx,edx ;最後のecx補正のため余りをebxに保存しておく
- mov ecx,eax ;商をカウンタに転送
- push ecx ;ブロック数計算のためecxの内容を保存しておく
- lodsd ;パターンデータを読み込む
- dec ecx ;カウンタ補正
- and eax,0ffffffh ;4バイト目をマスク
- mov edx,eax ;転送
- dec esi ;ポインタ補正
- L_PAT3: lodsd ;4バイト読み込む
- dec esi ;3バイトだけ読んだことにするためポインタを補正する
- and eax,0ffffffh ;4バイト目をマスク
- cmp eax,edx ;比較
- jnz PAT3j ;違ったらループアウト
- loop L_PAT3 ;ループチェック
- jmp PAT3j2
- PAT3j: sub esi,3 ;ポインタ補正
- PAT3j2: mov eax,edx ;データ転送
- pop edx ;ecx(Stack)->edx
- sub edx,ecx ;ブロック数計算
- lea ecx,[ecx][ecx*2] ;ecx=ecx*3
- add ecx,ebx ;残りデータ長を復活
- cmp edx,15 ;ブロック数は15を越えているか
- ja PAT32 ;上なら2バイトヘッダモードへ
- or dl,70h ;ヘッダ生成
- shl eax,8 ;ヘッダのスペースをアキュムレータ上に空ける
- mov al,dl ;ヘッダをアキュムレータにストア
- stosd ;データストア
- jmp PATEND ;ジャンプ
- PAT32: mov [edi+2],eax ;データストア
- or dx,6000h ;ヘッダ生成
- xchg dl,dh ;上下交換
- mov [edi],dx ;ヘッダストア
- add edi,5 ;ポインタ補正
- jmp PATEND ;ジャンプ
- ;
- PAT4: call GSET
- mov ebx,ecx
- and ebx,3
- shr ecx,2
- mov edx,ecx ;ブロック数計算のためecxの内容をedxに保存しておく
- lodsd ;パターンデータを読み込む
- dec ecx ;カウンタ補正
- push edi
- mov edi,esi
- repe scasd
- jz PAT4j ;カウントエンドでループアウトなら分岐
- inc ecx ;カウンタ補正
- sub edi,4
- PAT4j: mov esi,edi
- pop edi
- sub edx,ecx ;ブロック数計算
- shl ecx,2
- add ecx,ebx
- cmp edx,15
- ja PAT42
- or dl,90h
- mov [edi],dl
- inc edi
- stosd ;データストア
- jmp PATEND
- PAT42: mov [edi+2],eax
- or dx,8000h
- xchg dl,dh
- mov [edi],dx
- add edi,6
- jmp PATEND
- ;
- PAT5: call GSET
- mov ebx,5 ;残りデータ長を5で割る
- xor edx,edx
- mov eax,ecx
- div bx
- push edx ;最後のecx補正のため余りを保存しておく
- mov ecx,eax ;商をカウンタに転送
- mov edx,ecx ;ブロック数計算のためecxの内容を保存しておく
- lodsb ;最初の1バイトのパターンデータを読み込む
- mov bl,al ;blに転送
- lodsd ;後の4バイトを読み込む
- dec ecx ;カウンタ補正
- push edi ;保存
- mov edi,esi ;アドレスセット
- L_PAT5: inc edi ;最初の1バイトの比較
- cmp bl,[edi-1]
- jnz PAT5o ;違えばループアウト
- scasd ;次の4バイトの比較
- jnz PAT5e ;違えばループアウト
- loop L_PAT5 ;ループチェック
- jmp PAT5j
- PAT5e: sub edi,4 ;ポインタ補正
- PAT5o: sub edi,1 ;ポインタ補正
- PAT5j: mov esi,edi
- pop edi ;復帰
- sub edx,ecx ;ブロック数計算
- lea ecx,[ecx][ecx*4] ;ecx=ecx*5
- cmp edx,15 ;ブロック数は15を越えたか
- ja PAT52 ;上なら2バイトヘッダモードへ
- or dl,0B0h ;ヘッダ生成
- mov dh,bl ;データを転送
- mov [edi],dx ;データストア
- add edi,2 ;ポインタ補正
- stosd ;データストア
- pop ebx ;edx(Stack)->ebx
- add ecx,ebx ;残りデータ長計算
- jmp PATEND ;ジャンプ
- PAT52: mov [edi+2],bl ;データストア
- mov [edi+3],eax ;データストア
- or dx,0A000h ;ヘッダ生成
- xchg dl,dh ;上下交換
- mov [edi],dx ;ヘッダストア
- add edi,7 ;ポインタ補正
- pop ebx ;edx(Stack)->ebx
- add ecx,ebx ;残りデータ長計算
- ;
- PATEND: cmp point[ebp],edi ;非圧縮時より長いデータとなっていないか?
- jbe NONLINE ;長ければモードエンド
- cmp ecx,0 ;データを全てチェックしたか
- ja L_SET5 ;まだのこっていたら分岐
- ;
- LINEND: mov eax,outd[ebp] ;出力データ格納アドレスの先頭を得る
- sub edi,eax ;ブロックデータバイト数計算
- mov eax,edi
- mov esi,outd[ebp] ;出力データ格納アドレスの先頭をセット
- mov edi,work[ebp] ;最後に比較するため格納しておくアドレスをセット
- mov edx,eax ;データ数を退避しておく
- stosd ;最後の比較の為の数値をストア
- inc dword PTR [edi-4] ;数値の補正(ヘッダの分)
- cmp eax,7 ;データ数は7以上か
- ja LINED2 ;以上なら分岐
- ;
- or al,0C0h ;ヘッダ生成
- stosb ;ヘッダストア
- jmp LINTRS ;分岐
- ;
- NONLINE: ;圧縮データを生成出来なかったのでこのモードを
- mov work[ebp],0fffffffh ;選ばない様に、データをセットしておく
- jmp HIGCMP ;高圧縮モードへ
- ;
- LINED2: inc dword PTR [edi-4] ;2バイトヘッダなので数値をインクリメント
- or ax,8000h ;ヘッダ生成
- xchg ah,al ;上下交換
- stosw ;ヘッダストア
- ;
- LINTRS: mov ecx,edx ;退避しておいた値を復帰
- rep movsb ;データ転送
- ; 高圧縮モード
- HIGCMP:
- mov edx,lngth[ebp] ;現モードの比較の為にあらかじめ値を入れておく
- add edx,2
- mov ebx,work[ebp] ;比較の為のワーク領域の先頭アドレスを得る
- add ebx,wlength*4 ;現モードのアドレスを計算
- mov [ebx],edx ;ダミーカウンタ
- mov eax,nrefer[ebp] ;参照できるライン数を得る
- cmp eax,0 ;0か
- je LOWCMP ;0なら現モード終了
- dec eax ;計算の為-1する
- ;
- L_HIGC: mov edi,outd[ebp] ;出力データアドレスをセット
- mov point[ebp],edi ;値を保存
- mov esi,data[ebp] ;圧縮対象データアドレスをセット
- mov edi,refer[ebp] ;参照バッファアドレスを読み込む
- mov ecx,lngth[ebp] ;データ長を得る
- mov ngc[ebp],eax ;参照データナンバーを保存
- imul ax,nlength ;参照データアドレス計算
- add edi,eax
- ;
- call HIGCm ;高圧縮を行う
- ;
- mov eax,ngc[ebp] ;参照データナンバーを復帰
- sub eax,1 ;データナンバーをデクリメント
- jnc L_HIGC ;マイナスになって(全て参照)いなければループ
- jmp LOWCMP ;参照しおわったら低圧縮モードへ
- ;
- HIGCm: push ebx ;データバッファアドレス保存
- push edx ;生成データ長チェック値保存
- ;
- L_HICm: mov ebx,1 ;同データカウンタ(オフセットカウンタ)を初期化
- xor edx,edx ;異データカウンタをクリア
- L_HICc: cmpsb ;1バイト比較する
- jnz NONEQU ;違うデータなら分岐
- inc ebx ;同じなら同データカウンタをインクリメント
- loop L_HICc ;全てチェックしたか?していなければループ
- jmp HIEDin ;終わっていたら終了処理へ
- ;
- NONEQU: dec esi ;ポインタ補正
- dec edi ;ポインタ補正
- mov point+4[ebp],esi ;後のデータ転送の為ポインタを保存
- L_NOEQ: cmpsb ;1バイト比較する
- jz NOEQe ;同じデータなら分岐
- inc edx ;違うなら異データカウンタをインクリメント
- loop L_NOEQ ;全てチェックしたか?していなければループ
- NOEQe: dec esi ;ポインタ補正
- dec edi ;ポインタ補正
- xchg edi,point[ebp] ;出力データと参照データのアドレスを交換
- xchg esi,point+4[ebp] ;異データの先頭と現在の対象ポインタを交換
- cmp ebx,63 ;同データカウンタは63未満か
- ja NOEQ2 ;越えていたら2バイトブロックヘッダモードへ
- cmp edx,3 ;異データカウンタは3未満か
- ja NOEQ2 ;越えていたら2バイトブロックヘッダモードへ
- ;
- NOEQ1: jne NOEQST ;異データカウンタが3でなければ分岐
- dec edx ;異データカウンタをデクリメント
- mov eax,ebx ;同データカウンタをオフセットとしてeaxにセット
- or al,80h ;ヘッダ生成
- stosb ;ヘッダストア
- movsb ;データストア
- mov ebx,1 ;データオフセットカウンタを初期化
- NOEQST: mov eax,edx ;異データカウンタをeaxにセット
- dec eax ;データ2バイトフラグを作るためカウンタを-1
- shl al,6 ;データ2バイトフラグ生成
- or al,80h ;ヘッダ生成
- or al,bl ;データオフセットをヘッダにセット
- stosb ;ヘッダストア
- push ecx ;転送のためecxを保存
- mov ecx,edx ;データ数をセット
- rep movsb ;データ転送
- pop ecx ;ecx復帰
- jmp RECOMP ;データ長チェックへ分岐
- ;
- NOEQ2: mov eax,edx ;異データカウンタをeaxにセット
- xor edx,edx ;異データストアループためにカウンタをクリア
- cmp eax,15 ;異データカウンタは15以下か
- jbe CHGr ;以下なら分岐
- mov edx,eax ;異データ長セット
- sub edx,15 ;残りデータ長セット
- mov eax,15 ;取り合えず最初の15バイトをセット
- CHGr: push ecx ;対象データカウンタ保存
- mov ecx,eax ;転送データ長セット
- shl eax,11 ;異データ長をヘッダにセット
- or eax,ebx ;データオフセットをヘッダにセット
- mov ebx,1 ;データオフセットを初期化
- xchg al,ah ;上下交換
- stosw ;ヘッダストア
- rep movsb ;データ転送
- pop ecx ;対象データカウンタ復帰
- cmp edx,0 ;異データは残っているか
- jne NOEQ2 ;残っていたらループ
- ;
- RECOMP: xchg edi,point[ebp] ;出力データと参照データのアドレスを交換
- xchg esi,point+4[ebp] ;異データの先頭と現在の対象ポインタを交換
- cmp ecx,0 ;まだ圧縮していないデータは残っているか
- jne L_HICm ;残っていたらループ
- ;
- HIEDin: xchg edi,point[ebp] ;出力データと参照データのアドレスを交換
- sub edi,outd[ebp] ;圧縮データ長計算
- pop edx ;生成データ長復帰
- cmp edi,edx ;今までの値より今圧縮した方が短いか
- jb COMPt ;短ければワークエリアに転送
- CMPe: pop ebx ;長ければebxを復帰して
- ret ;リターン
- ;
- COMPt: mov edx,edi ;生成データ長を新しいものに交換
- mov esi,outd[ebp] ;転送元アドレスセット
- pop ebx ;転送先アドレスを復帰
- mov edi,ebx ;転送先アドレスをセット
- mov ecx,edx ;転送データ長セット
- mov eax,edx ;比較データ長セット
- add eax,2 ;ヘッダ長を足す
- stosd ;比較データ長ストア
- mov eax,ngc[ebp] ;参照ラインナンバーを得る
- or al,0D0h ;ヘッダ生成
- stosb ;トップヘッダストア
- mov eax,ecx ;ヘッダにデータ長をセット
- cmp eax,127 ;127バイトを越えたか
- jbe HIHEAD ;越えていなければ分岐
- inc dword PTR [edi-5] ;越えていれば比較データ長をインクリメント
- xchg ah,al ;上下交換
- stosw ;データカウンタヘッダストア
- rep movsb ;バッファにデータを転送する
- ret
- HIHEAD: or al,80h ;ヘッダ生成
- stosb ;ヘッダストア
- rep movsb ;バッファにデータを転送する
- ret
- ;
- ; 低圧縮モード
- LOWCMP:
- mov edi,work[ebp] ;比較のための保存アドレス計算
- add edi,wlength*2
- mov eax,0ffffffffh ;圧縮後のデータ長とヘッダをダミーで埋める
- stosd ;ダミーカウンタ
- stosb ;ダミートップヘッダ
- mov eax,nrefer[ebp] ;参照できるライン数を得る
- cmp eax,0 ;0か
- je CMPEND ;0なら分岐
- mov ebx,bml[ebp] ;ビットマップ長を読み込む
- add ebx,outd[ebp] ;データ格納領域先頭アドレス計算
- dec eax ;計算のため参照ラインナンバーを-1する
- mov edx,lngth[ebp] ;現モードの比較の為にあらかじめ値を入れておく
- add edx,2
- ;
- L_LWC:
- push eax ;参照ラインナンバー保存
- push edx ;mulにより下位16ビットが壊されるので保存
- mov esi,data[ebp] ;対象データ格納アドレスセット
- mov edi,refer[ebp] ;参照データ格納アドレス計算
- mov ecx,nlength
- mul ecx
- add edi,eax ;参照データ格納アドレスセット
- pop edx ;復帰
- ;
- call LOWCm ;低圧縮を行う
- ;
- pop eax ;復帰
- sub eax,1 ;データナンバーをデクリメント
- jnc L_LWC ;-1になって(全て参照)いなければループ
- jmp CMPEND ;参照しおわったら最終比較へ
- ;
- LOWCm: xor eax,eax ;ビットマップをクリアするためにeaxを0にする
- push edi ;参照データ格納アドレス保存
- mov edi,outd[ebp]
- mov ecx,bml[ebp] ;ビットマップ長セット
- rep stosb ;ビットマップクリア
- pop edi ;復帰
- mov ecx,lngth[ebp] ;データ長セット
- ;
- push ebx ;データ格納アドレス保存
- push edx ;生成データ長チェック値保存
- push ecx ;データ長保存
- dec dword PTR [esp]
- L_LOWC:
- repe cmpsb ;異データが見つかるまで比較
- jz LOWCe ;カウントエンドでループアウトなら分岐
- mov al,[esi-1] ;異データをロード
- mov [ebx],al ;異データをストア
- inc ebx ;データ格納ポインタを進める
- mov edx,[esp] ;全データ長を得る
- sub edx,ecx ;何ビット目で異データが出たか計算する
- mov eax,edx ;それをeaxにコピー
- shr edx,3 ;8で割る [ビットマップ先頭から何バイト目か]
- and eax,7 ;下位3ビットのみ有効 [そのバイトのどのビットか]
- add edx,outd[ebp] ;変更ビットマップのアドレスを得る
- bts [edx],ax ;対応ビットを立てる [ MSB:bit7 LSB:bit0 ]
- cmp ecx,0 ;全てのデータを処理したか
- ja L_LOWC ;していなければループ
- ;
- LOWCe: pop ecx ;スタック補正
- sub ebx,outd[ebp] ;処理済データ長を計算する
- pop edx ;生成データ長復帰
- cmp edx,ebx ;今までの値より今圧縮した方が短いか
- ja LOWCtr ;短ければワークエリアに転送
- ;
- pop ebx ;長ければebxを復帰して
- ret ;リターン
- ;
- LOWCtr: mov edx,ebx ;生成データ長を新しいものに交換
- mov eax,ebx ;現在のデータ長をeaxにコピー
- mov ecx,ebx ; 〃 ecxにコピー
- mov esi,outd[ebp] ;転送元アドレスセット
- mov edi,work[ebp] ;転送先アドレス計算
- add edi,wlength*2
- add eax,2 ;ヘッダ長(仮に2)を足す
- stosd ;カウンタストア
- mov eax,[esp+8] ;コール前に保存した参照ラインナンバーを得る
- or al,0D8h ;トップヘッダ生成
- stosb ;トップヘッダストア
- mov eax,ebx ;データバイト数をeaxにセット
- cmp eax,128 ;128以上か
- jae LOWH2 ;データバイト数ヘッダ2バイトモードへ
- or al,80h ;データバイト数ヘッダ生成
- stosb ; 〃 ストア
- jmp LOWH1 ;ジャンプ
- LOWH2: inc dword PTR [edi-5] ;データ長をインクリメント
- xchg al,ah ;上下交換
- stosw ;データバイト数ヘッダストア
- LOWH1: pop ebx ;ebx復帰
- rep movsb ;データ転送
- ret ;リターン
- ;
- ;
- CMPEND: ;圧縮後の各データ長比較
- mov ecx,lngth[ebp] ;非圧縮時のデータ長を得る
- xor ebx,ebx ;圧縮種類インデックスを初期化(0)
- mov edi,work[ebp] ;1次元圧縮モードのデータ長格納アドレスを得る
- ;
- CHKLIN:
- inc ecx ;非圧縮時のデータ長にヘッダ長を加える
- cmp ecx,[edi] ;非圧縮時と1次元圧縮時のデータ長を加える
- jbe CHKLOW ;非圧縮時の方が小さいか等しければ次の比較へ
- mov ebx,1 ;大きければインデックスを1次元圧縮モードに
- mov ecx,[edi] ;データ長を1次元圧縮モードに
- CHKLOW:
- cmp ecx,[edi+wlength*2] ;チェックしたデータ長と低圧縮モードを比べる
- jbe CHKHIG ;低圧縮モードの方が大きければ分岐
- mov ebx,2 ;小さければインデックスを低圧縮モードに
- mov ecx,[edi+wlength*2] ;データ長を低圧縮モードに
- CHKHIG:
- cmp ecx,[edi+wlength*4] ;チェックしたデータ長と高圧縮モードを比べる
- jbe CHKEND ;高圧縮モードの方が大きければ分岐
- mov ebx,3 ;インデックスを高圧縮モードに
- mov ecx,[edi+wlength*4] ;データ長を高圧縮モードに
- CHKEND:
- mov edi,outd[ebp] ;出力データ格納アドレスをセット
- cmp ebx,2 ;インデックスは2より小さいか
- jae CHKED2 ;小さくなければ分岐
- cmp ebx,0 ;インデックスは0より大きいか
- ja TRSLIN ;大きければ1次元圧縮データを転送
- ; ;大きくなければ非圧縮データを転送
- TRSNON:
- dec ecx ;ヘッダの分のデータ長を引く
- mov al,40h ;ヘッダ生成
- stosb ;ヘッダストア
- mov esi,data[ebp] ;非圧縮データの格納アドレスを得る
- rep movsb ;転送
- mov eax,lngth[ebp] ;本プログラム呼出元に返す値をセット
- inc eax ;ヘッダ長を加える
- jmp REGBUF
- ; 1次元圧縮データ転送
- TRSLIN:
- mov esi,work[ebp] ;1次元圧縮データの格納アドレスを得る
- TRSin: lodsd ;データ長を得る
- mov edx,eax ;呼出元へ渡すためにedxに保存しておく
- rep movsb ;転送
- mov eax,edx ;呼出元に返す値を復帰
- ;
- REGBUF: push eax
- mov esi,data[ebp] ;参照バッファを新たに登録しなおす
- mov eax,trsbuf[ebp]
- mov edi,nlength
- xor edx,edx
- mul edi
- add eax,refer[ebp]
- mov edi,eax
- mov ecx,lngth[ebp]
- mov edx,ecx
- and edx,3
- mov eax,[esi]
- mov [edi],eax
- add edi,edx
- add esi,edx
- shr ecx,2
- rep movsd
- pop eax
- ;
- add esp,worklng ;ワークエリア解放
- ret ;呼出元へリターン
- ;
- CHKED2: je TRSLOW
- ;
- TRSHIG:
- mov esi,work[ebp]
- add esi,wlength*4
- jmp TRSin
- ;
- TRSLOW:
- mov esi,work[ebp]
- add esi,wlength*2
- jmp TRSin
- ;
- ;
- ;
- EXEC endp
- CODE ends
- end
-