Многие программисты пользуются программой PKLite фирмы PKWare. Эта программа сжимает EXE – и COM-файлы. При сжатии этих файлов PKLITE’ом их объём уменьшается, а работают они так же, как и раньше. Разжимает программу в памяти PKLITE практически мгновенно. А нельзя ли использовать эту удобную утилиту для уменьшения объёма файлов, содержащих данные? Конечно, при этом можно сжимать не любые данные, а только те, которые будут использоваться в ВАШЕЙ программе. Сделать это очень просто. Для этого нужно дописать в начало данных маленький блок, сжать данные PKLITE’ом, а затем из главной программы с помощью процедуры EXEC загрузить и выполнить данные. Блок кода, который дописывается в начало данных, узнаёт, в какой точке находятся загруженные данные, и выходит в родительскую программу. Вот пример кода, дописываемого в начало файла для размера данных не более 64 K (создание COM-файла): xor ax, ax mov ds, ax mov word ptr ds:[7Ch], cs ret В шестнадцатеричном коде это выглядит так: 33, C0, 8E, D8, 8C, 0E, 7C, 00, C3. Как видите, при запуске и выполнении этого файла с данными он запишет по адресу 0000:007C значение сегмента кода. После возврата в главную программу будет известно, где начинаются загруженные данные. Адрес 0000:007C — это вектор прерывания графических символов 1Fh. Мы посылаем CS туда потому, что переменные родительской программы будут недоступны. Такой способ сжатия очень удобен для загрузки картинок и оверлеев. При этом программисту не нужно писать свой упаковщик. Я, например, успешно применяю PKLITE для сжатия картинок в играх. Но и у этого способа есть два основных недостатка. Первый: нужно всегда оставлять немного свободной памяти, необходимой для разворачивания файла. Второй: все сжатые файлы с данными должны создаваться во время написания главной программы. Вот программа, которая демонстрирует запуск и вывод на экран картинки для CGA адаптера размером 16000 байт: {$M 1024,0,0} {Heap — 0 байт. Всегда должно быть достаточно памяти, чтобы запустить и распаковать картинку.} uses Dos; var OldVec,w:word; Begin OldVec:=memW[0,$7C]; {Запоминаем старый вектор 1Fh} Exec(’SCREEN’); {«Запуск» и разжатие картинки} asm mov ax, 4 {Переход в графический CGA режим} int 10h end; w:=memW[0:$7C]+$10; {Узнаём сегмент кода загруженной программы + размер PSP} move(mem[w:9],mem[$B800:0],8000); {Вывод картинки} move(mem[w:8009],mem[$BA00:0],8000); {...} asm xor ax, ax {Ожидание нажатия [любой] клавиши [перед завершением программы]} int 16h mov ax, 3 {Возврат в текстовый режим} int 10h end; memW[0:$7C]:=OldVec {Возвращаем старое значение вектора 1Fh} End. [Hackers Club, IndexPro 1’95 ] ———————————— This document has been copied from FAVOR.com.ua (https://favor.com.ua/en/article/4941.html). All rights reserved by author of the material. In case of re-publication, the link to the source of the material is strongly required! Document date: August 15, 1994