Blog. Just Blog

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

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

Алгоритм MegaLZ был разработан участниками демо-группы MAYhEM для AmigaOS, но из открытых исходников можно собрать упаковщик для Windows. Степень компрессии неплохая, особенно на текстовых данных, на бинарных файлах чуть похуже. И при этом MegaLZ работает очень быстро как на упаковку, так и на распаковку, что тоже является его несомненным плюсом.

Из авторских исходников я скомпилировал консольную утилиту для упаковки и распаковки данных, она есть в прилагаемом к статье архиве. Упакованные данные идут сплошным потоком, в них не содержится никакой информации ни об их размере, ни о размере исходных данных.
  1. ;------------------------------------------------------------
  2. ; Распаковка данных в формате MegaLZ
  3. ;------------------------------------------------------------
  4. ; На входе:
  5. ;   lpCompressed - указатель на упакованные данные
  6. ;   lpOut - указатель на буфер для распакованных данных
  7. ; На выходе:
  8. ;   EAX = размер распакованных данных
  9. ;------------------------------------------------------------
  10. proc megalz_unpack lpCompressed:DWORD,lpOut:DWORD
  11.         pusha
  12.  
  13.         mov     esi,[lpCompressed]
  14.         mov     edi,[lpOut]
  15.  
  16.         mov     al,128
  17. .megalz_literal:
  18.         movsb
  19. .megalz_main:
  20.         stdcall .get_bit
  21.         jc      .megalz_literal
  22.         xor     edx,edx
  23.         mov     dh,-1
  24.         xor     ebx,ebx
  25.         push    2
  26.         pop     ecx
  27.         stdcall .get_bit
  28.         jc      .case_1x
  29.         stdcall .get_bit
  30.         jc      .megalz_short_offset
  31.         dec     ecx
  32.         mov     dl,63
  33. .read_3_bits:
  34.         stdcall .get_bit
  35.         adc     dl,dl
  36.         jnc     .read_3_bits
  37. .megalz_copy_bytes:
  38.         push    esi
  39.         movsx   edx,dx
  40.         lea     esi,[edi+edx]
  41.         rep     movsb
  42.         pop     esi
  43.         jmp     .megalz_main
  44. .case_1x:
  45.         stdcall .get_bit
  46.         jnc     .case_10
  47.         dec     ecx
  48. .read_log_len:
  49.         stdcall .get_bit
  50.         inc     ebx
  51.         jnc     .read_log_len
  52. .megalz_read_len:
  53.         stdcall .get_bit
  54.         adc     cl,cl
  55.         jc      .megalz_exit
  56.         dec     ebx
  57.         jnz     .megalz_read_len
  58.         inc     ecx
  59. .case_10:
  60.         inc     ecx
  61.         stdcall .get_bit
  62.         jnc     .megalz_short_offset
  63.         mov     dh,31
  64. .megalz_long_offset:
  65.         stdcall .get_bit
  66.         adc     dh,dh
  67.         jnc     .megalz_long_offset
  68.         dec     edx
  69. .megalz_short_offset:
  70.         mov     dl,[esi]
  71.         inc     esi
  72.         jmp     .megalz_copy_bytes
  73. .megalz_exit:
  74.         sub     edi,[lpOut]
  75.         mov     [esp+28],edi
  76.         popa
  77.         ret
  78.  
  79. .get_bit:
  80.         add     al,al
  81.         jnz     .exit_get_bit
  82.         lodsb
  83.         adc     al,al
  84. .exit_get_bit:
  85.         retn
  86. endp
В качестве параметров передается указатель на упакованные данные и указатель на буфер-приемник. На выходе в регистре EAX возвращается количество байт, которое было извлечено из сжатых данных. Размер принимающего буфера в процессе распаковки никак не проверяется, об этом вы должны позаботиться самостоятельно.

Так как размер исходных данных заранее не определен, перед распаковкой его надо обязательно узнать, чтобы выделить соответствующий объем памяти. Для этого я сделал следующую функцию.
  1. ;---------------------------------------------------
  2. ; Получение размера распакованных данных
  3. ;---------------------------------------------------
  4. ; На входе:
  5. ;   lpCompressed - указатель на упакованные данные
  6. ; На выходе:
  7. ;   EAX = размер распакованных данных
  8. ;---------------------------------------------------
  9. proc megalz_size lpCompressed:DWORD
  10.         pusha
  11.  
  12.         mov     esi,[lpCompressed]
  13.         xor     edi,edi
  14.  
  15.         mov     al,128
  16. .megalz_literal:
  17.         inc     esi
  18.         inc     edi
  19. .megalz_main:
  20.         stdcall .get_bit
  21.         jc      .megalz_literal
  22.         xor     edx,edx
  23.         mov     dh,-1
  24.         xor     ebx,ebx
  25.         push    2
  26.         pop     ecx
  27.         stdcall .get_bit
  28.         jc      .case_1x
  29.         stdcall .get_bit
  30.         jc      .megalz_short_offset
  31.         dec     ecx
  32.         mov     dl,63
  33. .read_3_bits:
  34.         stdcall .get_bit
  35.         adc     dl,dl
  36.         jnc     .read_3_bits
  37. .megalz_copy_bytes:
  38.         add     edi,ecx
  39.         jmp     .megalz_main
  40. .case_1x:
  41.         stdcall .get_bit
  42.         jnc     .case_10
  43.         dec     ecx
  44. .read_log_len:
  45.         stdcall .get_bit
  46.         inc     ebx
  47.         jnc     .read_log_len
  48. .megalz_read_len:
  49.         stdcall .get_bit
  50.         adc     cl,cl
  51.         jc      .megalz_exit
  52.         dec     ebx
  53.         jnz     .megalz_read_len
  54.         inc     ecx
  55. .case_10:
  56.         inc     ecx
  57.         stdcall .get_bit
  58.         jnc     .megalz_short_offset
  59.         mov     dh,31
  60. .megalz_long_offset:
  61.         stdcall .get_bit
  62.         adc     dh,dh
  63.         jnc     .megalz_long_offset
  64.         dec     edx
  65. .megalz_short_offset:
  66.         mov     dl,[esi]
  67.         inc     esi
  68.         jmp     .megalz_copy_bytes
  69. .megalz_exit:
  70.         mov     [esp+28],edi
  71.         popa
  72.         ret
  73.  
  74. .get_bit:
  75.         add     al,al
  76.         jnz     .exit_get_bit
  77.         lodsb
  78.         adc     al,al
  79. .exit_get_bit:
  80.         retn
  81. endp
В качестве единственного параметра передается указатель на упакованные данные, на выходе в регистре EAX количество байт, которое получится после распаковки.

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

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

MegaLZ.Unpack.Demo.zip (119,625 bytes)


Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 192 | Комментариев: 0

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

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

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

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