Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1149 | diamond | 1 | archiver.obj экспортирует две функции для распаковки deflate-данных. |
2 | |||
3 | Первая: deflate_unpack |
||
4 | Объявление в стиле Си: void* __stdcall deflate_unpack(const void* data, unsigned* pLength); |
||
5 | Аргументы: |
||
6 | data - указатель на упакованные данные |
||
7 | pLength - указатель на переменную длины: |
||
8 | на входе *pLength должно содержать длину входных данных data, |
||
9 | на выходе *pLength заполнится длиной выходных данных |
||
10 | Возвращаемое значение: |
||
11 | указатель на распакованные данные, NULL при нехватке памяти |
||
12 | память выделяет сам распаковщик, освободить её можно стандартной |
||
13 | функцией 68.13 |
||
14 | Пример вызова из ассемблерного кода: |
||
15 | ; пусть esi = указатель на данные, ecx = длина упакованных данных |
||
16 | push ecx ; переменная *pLength будет в стеке |
||
17 | push esp ; а вот и указатель на неё pLength |
||
18 | push esi ; а это данные |
||
19 | call [deflate_unpack] |
||
20 | pop ecx ; вытолкнем из стека переменную *pLength |
||
21 | ; два аргумента вытолкнет сама deflate_unpack |
||
22 | ; теперь eax = указатель на распакованные данные, ecx = их длина |
||
23 | |||
24 | Вторая: deflate_unpack2 |
||
25 | Объявление в стиле Си: void* __stdcall deflate_unpack2(const void* get_next_chunk, void* parameter, unsigned* pUnpackedLength); |
||
26 | void* __stdcall get_next_chunk(void* parameter, unsigned* pLength); |
||
27 | Аргументы: |
||
28 | get_next_chunk - указатель на функцию, возвращающую указатель и длину |
||
29 | очередного блока упакованных данных; когда данные |
||
30 | заканчиваются, должна возвращать NULL (при корректных |
||
31 | упакованных данных такой ситуации не может быть в принципе, |
||
32 | при некорректных данных если функция вернула NULL, то |
||
33 | дальнейших вызовов не будет) |
||
34 | parameter - сущность, которая не используется самим распаковщиком |
||
35 | и без изменений передаётся в get_next_chunk |
||
36 | (если callback-функции она тоже не нужна, можно передавать |
||
37 | в этом параметре всё, что угодно) |
||
38 | pUnpackedLength - указатель на переменную, куда будет записана |
||
39 | длина распакованных данных |
||
40 | Возвращаемое значение: |
||
41 | указатель на распакованные данные, NULL при нехватке памяти |
||
42 | память выделяет сам распаковщик, освободить её можно стандартной |
||
43 | функцией 68.13 |
||
44 | Пример вызова из ассемблерного кода: |
||
45 | push eax ; выделяем в стеке переменную для *pUnpackedLength |
||
46 | ; поскольку значение неважно, короче и быстрее всего |
||
47 | ; сделать это однобайтовым push <регистр> |
||
48 | push esp ; а вот и сам указатель pUnpackedLength |
||
49 | push esi ; какой-нибудь параметр |
||
50 | push deflate_callback |
||
51 | call [deflate_unpack2] |
||
52 | pop ecx ; выталкиваем UnpackedLength |
||
53 | ; как и в первом случае, eax = указатель на распакованные данные, ecx = размер |
||
54 | |||
55 | ... |
||
56 | |||
57 | ; а это функция получения следующего куска упакованных данных |
||
58 | deflate_callback: |
||
59 | ; если нужен параметр, то достать его можно так: |
||
60 | ; mov esi, [esp+4] ; esi = параметр |
||
61 | ; тут какие-то действия |
||
62 | ; и вот результат |
||
63 | mov ecx, [esp+8] ; в [ecx] нужно записать длину |
||
64 | mov [ecx], length |
||
65 | mov eax, buffer |
||
66 | ret 8регистр> |