|
Ниже приведен текст программы. Как и в программе LZSS здесь есть функции
побитового чтения/записи, но здесь они проще, т.к. читать и писать нужно только
по одному биту. Информация о кодах символов в архиве представлена в виде таблицы
чисел повторений - это не самый экономный способ, но зато самый простой.
Содержательная часть начинается с первого define - я понимаю, что возможность
вынести общие функции (ввод/вывод и т.п.) в отдельные файлы была бы полезна, но
пока ее нет.
struct Addr
word Ofs;
word Seg;
section
void @Ptr;
end
void @Ptr(word Seg,Ofs)
Addr P;
P.Seg=Seg;
P.Ofs=Ofs;
return @P.Ptr;
end
word GetPSP()
asm mov AH,62H
asm int 21H
asm mov AX,BX
end
word create(char @Name)
asm push DS
asm mov AH,3CH
asm mov CX,00H
asm mov DX,SS:[BP+6]
asm mov DS,DX
asm mov DX,SS:[BP+4]
asm int 21H
asm pop DS
end
word open(char @Name)
asm push DS
asm mov AH,3DH
asm mov AL,00H
asm mov DX,SS:[BP+6]
asm mov DS,DX
asm mov DX,SS:[BP+4]
asm int 21H
asm pop DS
end
word reset(word F)
asm push DS
asm mov AX,4200H
asm mov BX,SS:[BP+4]
asm mov CX,0
asm mov DX,0
asm int 21H
asm pop DS
end
word read(word F; void @Buff; word N)
asm push DS
asm mov AH,3FH
asm mov BX,SS:[BP+10]
asm mov CX,SS:[BP+4]
asm mov DX,SS:[BP+8]
asm mov DS,DX
asm mov DX,SS:[BP+6]
asm int 21H
asm pop DS
end
word write(word F; void @Buff; word N)
asm push DS
asm mov AH,40H
asm mov BX,SS:[BP+10]
asm mov CX,SS:[BP+4]
asm mov DX,SS:[BP+8]
asm mov DS,DX
asm mov DX,SS:[BP+6]
asm int 21H
asm pop DS
end
void close(word F)
asm mov AH,3EH
asm mov BX,SS:[BP+4]
asm int 21H
end
int strcmp(char @S1, @S2)
int P=0;
while TRUE do
if S1[P]S2[P] then
return 1;
end
if S1[P]=#0 then
return 0;
end
inc P;
end
end
void putc(char Ch)
asm mov AH,2
asm mov DL,SS:[BP+4]
asm int 21H
end
void puts(char @St)
word P=0;
while St[P]!=#0 do
putc(St[P]);
inc P;
end
end
struct long
word lo;
word hi;
end
void lInc(long @l)
if l.lo<65535 then
inc l.lo;
else
inc l.hi;
l.lo=0;
end
end
void lDec(long @l)
if l.lo>0 then
dec l.lo;
else
dec l.hi;
l.lo=65535;
end
end
long lSum(long a, b)
asm mov AX,SS:[BP+ 4]
asm mov DX,SS:[BP+ 6]
asm mov BX,SS:[BP+ 8]
asm mov CX,SS:[BP+10]
asm add AX,BX
asm db 013H ; adc DX,CX
asm db 0D1H
end
int lCmp(long a, b)
if a.hib.hi then
return 1;
end
if a.lob.lo then
return 1;
end
return 0;
end
define TXT_LEN 16384
define ARC_LEN 16384
define BLK_LEN 4096
define ARC_FWD 128
struct SNode
byte Code;
long Cnt;
int PP;
int P0;
int P1;
end
struct SInfo
byte Code;
long Cnt;
int Node;
end
SNode Tree [1024];
int Root;
int nNode;
int Indx [256];
void Init(long @Tabl) // построение дерева Хаффмана
SInfo Info[256];
int nInfo;
nInfo=0;
while nInfo<256 do
Info[nInfo].Code= nInfo;
Info[nInfo].Cnt = Tabl[nInfo];
Info[nInfo].Node=-1;
inc nInfo;
end
nNode=0;
while nInfo>1 do
int N0=0;
int N1=1;
if lCmp(Info[N0].Cnt,Info[N1].Cnt)<0 then
N0=1;
N1=0;
end
int I=2;
while I=0 then
Code(Tree[P].PP);
if Tree[Tree[P].PP].P0=P then
Save(0);
else
Save(1);
end
end
end
void Encode(word hArc, hTxt)
byte Txt [TXT_LEN]; // Текст
long Tabl [256]; // Таблица чисел повторений
int I=0;
while I<256 do
Tabl[I].lo=0;
Tabl[I].hi=0;
inc I;
end
int nTxt=0;
int pTxt=0;
while TRUE do
if pTxt>=nTxt then
nTxt=read(hTxt,@Txt,BLK_LEN);
if nTxt=0 then
exit
end
pTxt=0;
end
lInc(@Tabl[Txt[pTxt]]);
inc pTxt;
end
write(hArc,@Tabl,1024);
Init(@Tabl);
reset(hTxt);
nTxt=0;
pTxt=0;
pArc=0;
while TRUE do
if pTxt>=nTxt then
nTxt=read(hTxt,@Txt,BLK_LEN);
if nTxt=0 then
exit
end
pTxt=0;
end
if pArc>=BLK_LEN then
write(hArc,@Arc,pArc);
pArc=0;
end
Code(Indx[Txt[pTxt]]);
inc pTxt;
end
while pBit>0 do
Save(0);
end
Save(0);
if pArc>0 then
write(hArc,@Arc,pArc);
end
end
void Decode(word hArc, hTxt)
long Tabl [256];
read(hArc,@Tabl,1024);
Init(@Tabl);
byte Txt[TXT_LEN];
int nArc=0;
pArc=0;
long nTxt=Tree[Root].Cnt;
int pTxt=0;
while nTxt.hi>0 | nTxt.lo>0 do
if pTxt>=BLK_LEN then
write(hTxt,@Txt,pTxt);
pTxt=0;
end
if pArc+ARC_FWD>=nArc then
word I=pArc;
word J=0;
while I=0 do
if Load()=0 then
P=Tree[P].P0;
else
P=Tree[P].P1;
end
end
Txt[pTxt]=Tree[P].Code;
inc pTxt;
lDec(@nTxt);
end
if pTxt>0 then
write(hTxt,@Txt,pTxt);
end
end
begin
char @Line=@Ptr(GetPSP(),129); // Командная строка
byte @Size=@Ptr(GetPSP(),128); // Длина строки
char Parm [3][128]; // Параметры
int F=1;
int I=0;
int J=0;
while I<3 do
while J
Назад
|