Blog. Just Blog

Распаковка данных в формате LZF на Ассемблере

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Распаковка данных в формате LZF на Ассемблере
Распаковка данных в формате LZF на Ассемблере

Первоначально алгоритм компрессии LZF был разработан Marc Lehmann, но в последующем был немного оптимизирован и облегчен Ильей Муравьевым. По степени сжатия находится в одном ряду с LZE и LZ4, а по скорости упаковки и распаковки показывает просто отличные результаты. При этом основная оптимизация сжатия достигается при упаковке текстовых данных.

Авторская консольная утилита для упаковки и распаковки данных есть в прилагаемом к статье архиве. Упакованные данные идут сплошным потоком, в них не содержится никакой информации ни об их размере, ни о размере исходных данных. Никаких контрольных сумм для проверки целостности данных также не предусмотрено. Если это требуется, то вам придется реализовывать эти функции самостоятельно.
  1. ;------------------------------------------------------------
  2. ; Распаковка данных в формате LZF
  3. ;------------------------------------------------------------
  4. ; На входе:
  5. ;   lpCompressed - указатель на упакованные данные
  6. ;   lpOut - указатель на буфер для распакованных данных
  7. ; На выходе:
  8. ;   EAX = размер распакованных данных
  9. ;------------------------------------------------------------
  10. proc lzf_unpack lpCompressed:DWORD,lpOut:DWORD
  11.         pushad
  12.  
  13.         mov     edi,[lpOut]
  14.         mov     esi,[lpCompressed]
  15.  
  16.         xor     ecx,ecx
  17.         jmp     .loc_main_loop
  18. .loc_process:
  19.         push    eax
  20.         lodsb
  21.         rol     al,3
  22.         inc     al
  23.         and     al,00000111b
  24.         jnz     @f
  25.         lodsb
  26.         add     al,8
  27.         adc     ch,ch
  28. @@:
  29.         mov     cl,al
  30.         inc     ecx
  31.         pop     eax
  32.         cmp     al,20h
  33.         jnz     @f
  34.         xor     al,al
  35.         cmp     [esi],al
  36.         jz      .loc_done
  37. @@:
  38.         and     al,1Fh
  39.         push    esi
  40.         movzx   edx,byte[esi]
  41.         mov     dh,al
  42.         movsx   edx,dx
  43.  
  44.         mov     esi,edi
  45.         sbb     esi,edx
  46.  
  47.         rep     movsb
  48.         pop     esi
  49.         inc     esi
  50. .loc_main_loop:
  51.         mov     al,[esi]
  52.         cmp     al,20h
  53.         jnc     .loc_process
  54.         inc     al
  55.         mov     cl,al
  56.         inc     esi
  57.         rep     movsb
  58.         jmp     .loc_main_loop
  59. .loc_done:
  60.         sub     edi,[lpOut]
  61.         mov     [esp+28],edi
  62.  
  63.         popad
  64.         ret
  65. endp
В качестве параметров передается указатель на упакованные данные и указатель на буфер-приемник. На выходе в регистре EAX возвращается количество байт, которое было извлечено из сжатых данных. Размер принимающего буфера в процессе распаковки никак не проверяется, об этом вы должны позаботиться самостоятельно.

Так как размер исходных данных заранее не определен, перед распаковкой его надо обязательно узнать, чтобы выделить соответствующий объем памяти. Для этого я сделал следующую функцию.
  1. ;------------------------------------------------------------
  2. ; Получение размера распакованных данных
  3. ;------------------------------------------------------------
  4. ; На входе:
  5. ;   lpCompressed - указатель на упакованные данные
  6. ; На выходе:
  7. ;   EAX = размер распакованных данных
  8. ;------------------------------------------------------------
  9. proc lzf_size lpCompressed:DWORD
  10.         pushad
  11.  
  12.         mov     esi,[lpCompressed]
  13.         xor     edi,edi
  14.  
  15.         xor     ecx,ecx
  16.         jmp     .loc_main_loop
  17. .loc_process:
  18.         push    eax
  19.         lodsb
  20.         rol     al,3
  21.         inc     al
  22.         and     al,00000111b
  23.         jnz     @f
  24.         lodsb
  25.         add     al,8
  26.         adc     ch,ch
  27. @@:
  28.         mov     cl,al
  29.         inc     ecx
  30.         pop     eax
  31.         cmp     al,20h
  32.         jnz     @f
  33.         xor     al,al
  34.         cmp     [esi],al
  35.         jz      .loc_done
  36. @@:
  37.         add     edi,ecx
  38.         xor     ecx,ecx
  39.         inc     esi
  40. .loc_main_loop:
  41.         mov     al,[esi]
  42.         cmp     al,20h
  43.         jnc     .loc_process
  44.         inc     al
  45.         mov     cl,al
  46.         inc     esi
  47.  
  48.         add     esi,ecx
  49.         add     edi,ecx
  50.         xor     ecx,ecx
  51.         jmp     .loc_main_loop
  52. .loc_done:
  53.         mov     [esp+28],edi
  54.  
  55.         popad
  56.         ret
  57. endp
В качестве единственного параметра передается указатель на упакованные данные, на выходе в регистре EAX количество байт, которое получится после распаковки.

В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму LZF, и выводит ее на форму. Там же в архиве утилита для упаковки и распаковки данных от Ильи Муравьева.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

LZF.Unpack.Demo.zip (54,704 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 182 | Комментариев: 1

Комментарии

Отзывы посетителей сайта о статье
kimstiк (26.01.2024 в 11:45):
красиво. жалко что Илья не опубликовал финальный код своего оптимального LZ4 компрессора :(

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.1 сек. / MySQL: 2 (0.0036 сек.) / Память: 4.5 Mb
Наверх