Blog. Just Blog

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

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

Программиста Joergen Ibsen вы можете знать, как автора популярной библиотеки aPLib и DOS'овского упаковщика исполняемых файлов aPACK, который на протяжении многих лет неизменно занимал первые строки рейтингов по степени компрессии. Про aPLib поговорим позже, а сегодня будет распаковщик для еще одной разработки Joergen Ibsen - BriefLZ. Это высокоскоростная разновидность Lempel-Ziv алгоритма для сжатия данных, по степени компрессии приближающаяся к zlib.

Заголовок упакованных данных, на мой взгляд, несколько избыточен. Тут контрольные суммы CRC32 упакованных и исходных данных, размер упакованных и исходных данных, формат данных и сигнатура, всего 6 DWORD'ов. Для больших объемов данных это погоды не делает, а на маленьких блоках информации десяток-другой байт можно было бы и сэкономить. Впрочем, автору виднее. Исходники открыты, при необходимости упаковщик можно модифицировать. Из всего заголовка нас интересует 5-й DWORD, в котором содержится размер исходных данных. Для приведения этого DWORD'а в нужный вид к нему придется дополнительно применить команду BSWAP. Эта информация потребуется при определении размера буфера-приемника для распакованных данных.

В официальных исходниках есть пример упаковщика, но вот собирать его мне пришлось самостоятельно. В комментариях к одной из статей меня как-то спросили, зачем я вкладываю в архивы с примерами уже скомпилированные файлы. Вот именно затем и вкладываю. Заставлять пользователя устанавливать среду типа Visual Studio или MinGW, в которой можно собрать авторские исходники, а потом настраивать ее в соответствии с авторским видением окружения, - это неимоверно напрягает. Это же касается и сборки релизов только под x64, если такой вариант не является единственно возможным. Не будем о грустном, переходим к коду распаковщика.
  1. ;------------------------------------------------------------
  2. ; Распаковка данных в формате BriefLZ
  3. ;------------------------------------------------------------
  4. ; На входе:
  5. ;   lpCompressed - указатель на упакованные данные
  6. ;   lpOut - указатель на буфер для распакованных данных
  7. ; На выходе:
  8. ;   EAX = размер распакованных данных
  9. ;------------------------------------------------------------
  10. proc brieflz_unpack lpCompressed:DWORD,lpOut:DWORD
  11.         pusha
  12.         mov     esi,[lpCompressed]
  13.         mov     edi,[lpOut]
  14.         mov     ebx,edi
  15.         lodsd
  16.         lodsd
  17.         lodsd
  18.         lodsd
  19.         lodsd
  20.         bswap   eax
  21.         add     ebx,eax
  22.         lodsd
  23.  
  24.         mov     ax,8000h
  25. .brieflz_literal:
  26.         movsb
  27. .brieflz_main:
  28.         cmp     edi,ebx
  29.         jnb     .brieflz_exit
  30.  
  31.         stdcall .brieflz_getbit
  32.         jnc     .brieflz_literal
  33.  
  34. .brieflz_getgamma:
  35.         pushfd
  36.         cdq
  37.         inc     edx
  38. .brieflz_gamma_loop:
  39.         stdcall .brieflz_getbit
  40.         adc     edx,edx
  41.         stdcall .brieflz_getbit
  42.         jc      .brieflz_gamma_loop
  43.  
  44.         popfd
  45.         cmovc   ecx,edx
  46.         cmc
  47.         jnc     .brieflz_getgamma
  48.  
  49.         dec     edx
  50.         dec     edx
  51.  
  52.         inc     ecx
  53.         inc     ecx
  54.  
  55.         shl     edx,8
  56.         mov     dl,[esi]
  57.         inc     esi
  58.         inc     edx
  59.  
  60.         push    esi
  61.         mov     esi,edi
  62.         sub     esi,edx
  63.         rep     movsb
  64.         pop     esi
  65.         jmp     .brieflz_main
  66.  
  67. .brieflz_getbit:
  68.         add     ax,ax
  69.         jnz     .brieflz_exit_getbit
  70.         lodsw
  71.         adc     ax,ax
  72. .brieflz_exit_getbit:
  73.         retn
  74.  
  75. .brieflz_exit:
  76.         sub     edi,[lpOut]
  77.         mov     [esp+28],edi
  78.         popa
  79.         ret
  80. endp
В качестве параметров передается указатель на упакованные данные и указатель на буфер-приемник. На выходе в регистре EAX возвращается количество байт, которое было извлечено из сжатых данных. Размер принимающего буфера в процессе распаковки никак не проверяется, об этом вы должны позаботиться самостоятельно.

В приложении пример программы с исходным текстом, которая извлекает из памяти иконку, упакованную по алгоритму BriefLZ, и выводит ее на форму. Там же в архиве утилита для упаковки и распаковки данных от Joergen Ibsen.

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

BriefLZ.Unpack.Demo.zip (29,508 bytes)


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

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
DRON (10.02.2021 в 17:58):
Там вроде --optimal надо для максимального сжатия передавать, а не -9, но результаты всё равно хуже чем у aPLib.

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

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

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