Распаковка данных в формате LZRW1 на Ассемблере
Распаковка данных в формате LZRW1 на Ассемблере
Алгоритм компрессии LZRW1 был создан в далеких 90-х годах Ross N. Williams на базе оригинальных алгоритмов серии LZ77. Основной упор при разработке был сделан на максимальную скорость обработки данных, но при этом пришлось пожертвовать степенью сжатия. И действительно, по качеству сжатия LZRW1 недалеко ушел от LZ77, зато даже большие файлы упаковывает буквально за доли секунды.
В прилагаемом архиве я собрал все доступные исходники оригинального алгоритма, а также авторскую статью, в которой описываются основные технические детали. На базе демонстрационной программы мне даже удалось скомпилировать кривенький, но более-менее работающий упаковщик данных в формате LZRW1. Он также находится в архиве.
Особенностью этого формата является то, что в процессе распаковки невозможно достоверно определить конец упакованных данных, поэтому в процедуру распаковщика приходится передавать размер упакованных данных в явном виде.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Распаковка данных в формате LZRW1
- ;------------------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; lpOut - указатель на буфер для распакованных данных
- ; dSize - размер упакованных данных
- ; На выходе:
- ; EAX = размер распакованных данных
- ;------------------------------------------------------------
- proc lzrw1_unpack lpCompressed:DWORD, lpOut:DWORD, dSize:DWORD
- pusha
- push ebp
- mov esi,[lpCompressed]
- mov edi,[lpOut]
- mov ebp,[dSize]
- add ebp,esi
- lodsd
- xor eax,eax
- .loc_process:
- push 17
- pop edx
- lodsw
- xchg ebx,eax
- .loc_loop:
- cmp esi,ebp
- je .loc_done
- dec edx
- jz .loc_process
- shr ebx,1
- jc @f
- movsb
- jmp .loc_loop
- @@:
- lodsb
- aam 16
- cwde
- movzx ecx,al
- inc ecx
- lodsb
- push esi
- mov esi,edi
- sub esi,eax
- rep movsb
- pop esi
- jmp .loc_loop
- .loc_done:
- pop ebp
- sub edi,[lpOut]
- mov [esp+28],edi
- popa
- ret
- endp
Так как размер исходных данных заранее не определен, перед распаковкой его надо обязательно узнать, чтобы выделить соответствующий объем памяти. Для этого я сделал следующую функцию.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Получение размера распакованных данных
- ;------------------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; dSize - размер упакованных данных
- ; На выходе:
- ; EAX = размер распакованных данных
- ;------------------------------------------------------------
- proc lzrw1_size lpCompressed:DWORD, dSize:DWORD
- pusha
- push ebp
- mov esi,[lpCompressed]
- mov ebp,[dSize]
- add ebp,esi
- xor edi,edi
- lodsd
- xor eax,eax
- .loc_process:
- push 17
- pop edx
- lodsw
- xchg ebx,eax
- .loc_loop:
- cmp esi,ebp
- je .loc_done
- dec edx
- jz .loc_process
- shr ebx,1
- jc @f
- inc esi
- inc edi
- jmp .loc_loop
- @@:
- lodsb
- aam 16
- cwde
- movzx ecx,al
- inc ecx
- lodsb
- add edi,ecx
- jmp .loc_loop
- .loc_done:
- pop ebp
- mov [esp+28],edi
- popa
- ret
- endp
В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму LZRW1, и выводит ее на форму.
Просмотров: 239 | Комментариев: 0
Метки: Assembler, распаковка
Комментарии
Отзывы посетителей сайта о статье
Комментариeв нет
Добавить комментарий
Заполните форму для добавления комментария