Распаковка данных в формате LZF на Ассемблере
Распаковка данных в формате LZF на Ассемблере
Первоначально алгоритм компрессии LZF был разработан Marc Lehmann, но в последующем был немного оптимизирован и облегчен Ильей Муравьевым. По степени сжатия находится в одном ряду с LZE и LZ4, а по скорости упаковки и распаковки показывает просто отличные результаты. При этом основная оптимизация сжатия достигается при упаковке текстовых данных.
Авторская консольная утилита для упаковки и распаковки данных есть в прилагаемом к статье архиве. Упакованные данные идут сплошным потоком, в них не содержится никакой информации ни об их размере, ни о размере исходных данных. Никаких контрольных сумм для проверки целостности данных также не предусмотрено. Если это требуется, то вам придется реализовывать эти функции самостоятельно.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Распаковка данных в формате LZF
- ;------------------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; lpOut - указатель на буфер для распакованных данных
- ; На выходе:
- ; EAX = размер распакованных данных
- ;------------------------------------------------------------
- proc lzf_unpack lpCompressed:DWORD,lpOut:DWORD
- pushad
- mov edi,[lpOut]
- mov esi,[lpCompressed]
- xor ecx,ecx
- jmp .loc_main_loop
- .loc_process:
- push eax
- lodsb
- rol al,3
- inc al
- and al,00000111b
- jnz @f
- lodsb
- add al,8
- adc ch,ch
- @@:
- mov cl,al
- inc ecx
- pop eax
- cmp al,20h
- jnz @f
- xor al,al
- cmp [esi],al
- jz .loc_done
- @@:
- and al,1Fh
- push esi
- movzx edx,byte[esi]
- mov dh,al
- movsx edx,dx
- mov esi,edi
- sbb esi,edx
- rep movsb
- pop esi
- inc esi
- .loc_main_loop:
- mov al,[esi]
- cmp al,20h
- jnc .loc_process
- inc al
- mov cl,al
- inc esi
- rep movsb
- jmp .loc_main_loop
- .loc_done:
- sub edi,[lpOut]
- mov [esp+28],edi
- popad
- ret
- endp
Так как размер исходных данных заранее не определен, перед распаковкой его надо обязательно узнать, чтобы выделить соответствующий объем памяти. Для этого я сделал следующую функцию.
Code (Assembler) : Убрать нумерацию
- ;------------------------------------------------------------
- ; Получение размера распакованных данных
- ;------------------------------------------------------------
- ; На входе:
- ; lpCompressed - указатель на упакованные данные
- ; На выходе:
- ; EAX = размер распакованных данных
- ;------------------------------------------------------------
- proc lzf_size lpCompressed:DWORD
- pushad
- mov esi,[lpCompressed]
- xor edi,edi
- xor ecx,ecx
- jmp .loc_main_loop
- .loc_process:
- push eax
- lodsb
- rol al,3
- inc al
- and al,00000111b
- jnz @f
- lodsb
- add al,8
- adc ch,ch
- @@:
- mov cl,al
- inc ecx
- pop eax
- cmp al,20h
- jnz @f
- xor al,al
- cmp [esi],al
- jz .loc_done
- @@:
- add edi,ecx
- xor ecx,ecx
- inc esi
- .loc_main_loop:
- mov al,[esi]
- cmp al,20h
- jnc .loc_process
- inc al
- mov cl,al
- inc esi
- add esi,ecx
- add edi,ecx
- xor ecx,ecx
- jmp .loc_main_loop
- .loc_done:
- mov [esp+28],edi
- popad
- ret
- endp
В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму LZF, и выводит ее на форму. Там же в архиве утилита для упаковки и распаковки данных от Ильи Муравьева.
Просмотров: 283 | Комментариев: 1
Метки: Assembler, распаковка
Комментарии
Отзывы посетителей сайта о статье
kimstiк
(26.01.2024 в 11:45):
красиво. жалко что Илья не опубликовал финальный код своего оптимального LZ4 компрессора :(
Добавить комментарий
Заполните форму для добавления комментария