TMTSTUB
DOS ЭКСТЕНДЕР ДЛЯ TMT PASCAL
( Часть 2 )
Автор: Рустам Гадеев, 15 May 98
Если вы заметили в документе
опечатки или неточности перевода,
просьба сообщить о них!
Перевод на русский язык и оформление:
Валерий Вотинцев
СОДЕРЖАНИЕ:
ВВЕДЕНИЕ
ПРОГРАММНЫЙ ИНТЕРФЕЙС (API) TMTSTUB
1. ПОДДЕРЖКА DOS32 API
Установка текущей позиции в файле
Загрузить и/или выполнить программу
Получить информацию о DOS32 адресе
Отменить предыдущее выделение памяти
Выделить блок памяти
2. ПОДДЕРЖКА ИНТЕРФЕЙСА WDOSX API
2.1. Прерывания и исключения
2.2. Распределение памяти
3. ПРОГРАММНЫЙ ИНТЕРФЕЙС WDOSX (API)
3.1. Поддерживаемые функции DPMI 0.9
3.2. Расширенный интерфейс DOS INT 21H (EXTENDED DOS API)
3.3. Расширенные функции поддержки МЫШИ
3.4. Прочие функции WDOSX
ПЛАНЫ НА БУДУЩЕЕ
3.2. РАСШИРЕННЫЙ ИНТЕРФЕЙС DOS INT 21H (EXTENDED DOS API)
Перечень поддерживаемых функций:
| 09h | Вывод строки на консоль |
Write string to console |
| 1Ah | Установить адрес DTA (disk transfer area) |
Set disk transfer area address |
| 1Bh | Получить характеристики текущего диска |
Get allocation information for default drive |
| 1Ch | Получить характеристики указанного диска |
Get allocation information for specific drive |
| 1Fh | Получить DPB (drive parameter block)
для текущего диска |
Get drive parameter block for default drive |
| 25h | Установить обработчик прерывания
(Set interrupt vector) |
Set interrupt vector |
| 2Fh | Получить адрес DTA (disk transfer area) |
Get disk transfer area address |
| 32h | Получить DPB (drive parameter block)
для указанного диска |
Get drive parameter block for specific drive |
| 34h | Получить адрес флага InDos |
Get address of InDos flag |
| 35h | Получить адрес обработчика прерывания |
Get interrupt vector |
| 39h | Создать каталог (директорий) |
Create subdirectory |
| 3Ah | Удалить каталог (директорий) |
Remove subdirectory |
| 3Bh | Изменить текущий каталог |
Change current directory |
| 3Ch | Создать новый файл |
Create new file |
| 3Dh | Открыть существующий файл |
Open existing file |
| 3Fh | Чтение из файла |
Read from file |
| 40h | Запись в файл |
Write to file |
| 41h | Удалить файл с диска |
Delete file |
| 43h | Получить/Установить атрибуты файла |
Get/set file attributes |
| 44h | IOCTL |
IOCTL |
| 47h | Получить имя текущего каталога |
Get current directory |
| 48h | Выделить блок памяти DOS |
Allocate DOS memory block |
| 49h | Освободить блок памяти DOS |
Free DOS memory block |
| 4Ah | Изменить размер блока памяти DOS |
Resize DOS memory block |
| 4Bh | Загрузить и выполнить программы |
Load and execute child program |
| 4Eh | Найти первый файл по маске (Find first) |
Find first matching file |
| 4Fh | Найти следующий файл по маске (Find next) |
Find next matching file |
| 56h | Переименовать файл |
Rename file |
| 5Ah | Создать временный файл |
Create temporary file |
| 5Bh | Создать новый файл |
Create new file |
Подробное описание функций WDOSX для расширенного интерфейса DOS INT 21h:
9h - Вывод строки на консоль
Вход:
AH = 09h
DS:EDX -> адрес строки, завершающейся символом '$'
Примечание:
Размер выводимой строки не должен превышать 16k,
поскольку именно такой размер у буфера передачи WDOSX.
1Ah - Установить адрес DTA (disk transfer area)
Вход:
AH = 1Ah
DS:EDX -> Новый адрес DTA (Disk Transfer Area)
Примечание:
WDOSX имеет свой внутреннй буфер для DTA.
При вызове FindFirst / FindNext, WDOSX производит
необходимое копирование в него, чтобы сделать прозрачным
доступ к DTA из пользовательской программы.
1Bh - Получить характеристики текущего диска
Вход:
AH = 1Bh
Выход:
AL = Количество секторов в кластере
CX = Количество байт в секторе
DX = Общее количество кластеров
DS:EBX -> Байт идентификации (media ID byte)
1Ch - Получить характеристики указанного диска
Вход:
AH = 1Bh
DL = номер диска (0 = текущий, 1 = A: и т.д.)
Выход:
AL = Количество секторов в кластере
CX = Количество байт в секторе
DX = Общее количество кластеров
DS:EBX -> Байт идентификации (media ID byte)
1Fh - Получить DPB (drive parameter block) для текущего диска
Вход:
AH = 1Fh
Выход:
AL = статус (0 = успешно, -1 = неверно указан диск)
DS:EBX -> Адрес DBB (Drive Parameter Block)
25h - Установить обработчик прерывания
Вход:
AH = 25h
AL = номер прерывания
DS:EDX -> адрес нового обработчика прерывания
Примечание:
Эта функция устанавливает обработчик для защищенного
режима с использованием функции 0205h DPMI.
2Fh - Получить адрес DTA (disk transfer area)
Вход:
AH = 2Fh
Выход:
ES:EBX -> Адрес DTA (Disk Transfer Area)
Примечание:
Если новый адрес DTA не был установлен,
то будет возвращен адрес DTA по умолчанию (PSP:80h).
В противном случае возвращается адрес,
ранее установленный с помощью функции 1Ah.
32h - Получить DPB (drive parameter block) указанного диска
Вход:
AH = 32h
DL = номер диска (0 = текущий, 1 = A: и т.д.)
Выход:
AL = статус (0 = успешно, -1 = неверно указан диск)
DS:EBX -> адрес DPB (Drive Parameter Block)
34h - Получить адреса флага InDos
Вход:
AH = 34h
Выход:
ES:EBX -> Адрес флага InDos
35h - Получить адрес обработчика прерывания
Вход:
AH = 35h
AL = номер прерывания
Выход:
ES:EBX -> адрес обработчика указанного прерывания
Примечание:
Эта функция возвращает адрес обработчика защищенного
режима с помощью функции 0204h DPMI.
39h - Создать каталог
Вход:
AH = 39h
DS:EDX -> Имя каталога в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно,
CF = установлен, если произошла ошибка
(AX = код ошибки)
3Ah - Удалить каталог
Вход:
AH = 3Ah
DS:EDX -> Имя каталога в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно,
CF = установлен, если произошла ошибка
(AX = код ошибки)
3Bh - Изменить текущий каталог
Вход:
AH = 3Bh
DS:EDX -> Имя каталога в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно,
CF = установлен, если произошла ошибка
(AX = код ошибки)
3Ch - Создать новый файл
Вход:
AH = 3Ch
CX = байт атрибутов файла
DS:EDX -> Имя файла в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно
(AX - дескриптор файла),
CF = установлен, если произошла ошибка
(AX = код ошибки)
3Dh - Открыть существующий файл
Вход:
AH = 3Dh
AL = Режим открытия (access mode)
DS:EDX -> Имя файла в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно
(AX - дескриптор файла),
CF = установлен, если произошла ошибка
(AX = код ошибки)
3Fh - Чтение из файла
Вход:
AH = 3Fh
BX = дескриптор файла
ECX = количество байт для чтения
DS:EDX -> адрес буфера для записи считанных данных
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически прочитанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет прочитать за одно обращение до
4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
40h - Запись в файл
Вход:
AH = 40h
BX = дескриптор файла
ECX = количество записываемых байт
DS:EDX -> адрес буфера с данными
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически записанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет записать за одно обращение до
4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
41h - Удалить файл
Вход:
AH = 41h
DS:EDX -> Имя файла в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно,
CF = установлен, если произошла ошибка
(AX = код ошибки)
43h - Получить/установить атрибуты файла
Вход:
AH = 43h
AL = номер подфункции (0 = получить, 1 = установить)
DS:EDX -> Имя файла в формате ASCIZ
Если на входе AL = 1, то
CX = новые атрибуты файла
Выход:
CF = сброшен, если операция прошла успешно,
CF = установлен, если произошла ошибка
(AX = код ошибки)
CX = полученные атрибуты файла
44h - IOCTL
Вход:
AH = 44h
AL = номер подфункции
Расширены следующие подфункции функции 44h:
AL = 2 (чтение из символьного устройства)
BX = дескриптор файла
ECX = количество байт для чтения
DS:EDX -> буфер для прочитанных данных
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически прочитанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет прочитать за одно обращение
до 4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
Перед вызовом оригинальной функции DOS, производится
копирование максимального количества байт (ECX,16k)
из DS:EDX в буфер передачи для реального режима для
обеспечения передачи структуру запроса.
AL = 3 (запись в символьное устройство)
BX = дескриптор файла
ECX = количество записываемых байт
DS:EDX -> буфер с данными для записи
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически записанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет записать за одно обращение до
4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
AL = 4 (чтение из устройства блочного типа)
BL = номер диска (0 = текущий, 1 = A: и т.д.)
ECX = количество байт для чтения
DS:EDX -> буфер данных
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически прочитанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет прочитать за одно обращение
до 4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
Перед вызовом оригинальной функции DOS, производится
копирование максимального количества байт (ECX,16k)
из DS:EDX в буфер передачи для реального режима для
обеспечения передачи структуру запроса.
AL = 5 (запись в устройство блочного типа)
BL = номер диска (0 = текущий, 1 = A: и т.д.)
ECX = количество записываемых байт
DS:EDX -> буфер данных
Выход:
CF = сброшен, если операция прошла успешно
(EAX - количество фактически записанных байт),
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
Эта функция позволяет записать за одно обращение
до 4 гигабайт. В отличие от чистого DOS, здесь нет
ограничения в 64k.
47h - Получить имя текущего каталога
Вход:
AH = 47h
DL = номер диска (0 = текущий, 1 = A: и т.д.)
DS:ESI -> 64-байтный буфер для имени каталога
в формате ASCIZ
Выход:
DS:ESI -> имя каталога в формате ASCIZ
CF = сброшен, если операция прошла успешно
CF = установлен, если произошла ошибка
(AX = код ошибки)
48h - Выделить блок памяти DOS
Вход:
AH = 48h
BX = количество выделяемых параграфов
Выход:
CF = сброшен, если операция прошла успешно
(AX = селектор выделенного блока)
CF = установлен, если произошла ошибка
(AX = код ошибки,
BX = размер максимального блока)
49h - Освободить блок памяти DOS
Вход:
AH = 49h
ES = селектор освобождаемого блока
Выход:
CF = сброшен, если операция прошла успешно
CF = установлен, если произошла ошибка
(AX = код ошибки)
4Ah - Изменить размер блока памяти DOS
Вход:
AH = 4Ah
BX = новый размер блока в параграфах
ES = селектор изменяемого блока
Выход:
CF = сброшен, если операция прошла успешно
CF = установлен, если произошла ошибка
(AX = код ошибки,
BX = размер максимального блока)
4Bh - Загрузить и выполнить программу
Вход:
AH = 4BH
AL = 0 (прочие подфункции НЕ поддерживаются)
DS:EDX -> имя выполняемой программы
в формате ASCIZ
ES:EBX -> блок параметров (см. ниже)
Выход:
CF = сброшен, если операция прошла успешно
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
В отличие от чистого DOS, WDOSX имеет
следующий формат блока параметров:
Смещение 00000000: 48-битный дальний указатель
защищенного режима на используемое
окружение
Смещение 00000006: 48-битный дальний указатель
защищенного режима на переданную
программе командную строку
Такой же метод используют и большинство других DOS
экстендеров, так что проблем с совместимостью
возникнуть не должно.
4Eh - Поиск первого файла по маске (Find first)
Вход:
AH = 4Eh
AL = флаг, используемый командой APPEND
CX = маска атрибутов файла
DS:EDX -> маска имени файла в формате ASCIZ,
включая путь
Выход:
CF = сброшен, если операция прошла успешно
(используется DTA, установленный функцией 1Ah)
CF = установлен, если произошла ошибка
(AX = код ошибки)
4Fh - Поиск следующего файла по маске (Find next)
Вход:
AH = 4Fh
Выход:
CF = сброшен, если операция прошла успешно
(используется DTA, установленный функцией 1Ah)
CF = установлен, если произошла ошибка
(AX = код ошибки)
Примечание:
При повторном поиске используется информация из DTA,
содержащая параметры, установленные при предыдущем
вызове Find First (функция 4Eh).
56h - Переименовать файл
Вход:
AH = 56h
DS:EDX -> старое имя файла в формате ASCIZ
ES:EDI -> новое имя файла в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно
CF = установлен, если произошла ошибка
(AX = код ошибки)
5Ah - Создать временный файл
Вход:
AH = 5Ah
CX = атрибуты файла
DS:EDX -> буфер, содержащий полный путь
к создаваемому файлу,
завершающийся обратным слэшем ("\")
+ 13-ю нулевыми байтами.
Выход:
CF = сброшен, если операция прошла успешно
DS:EDX -> полное имя временного файла.
CF = установлен, если произошла ошибка
(AX = код ошибки)
5Bh - Создать новый файл
Вход:
AH = 5Bh
CX = атрибуты файла
DS:EDX -> имя и путь создаваемого файла
в формате ASCIZ
Выход:
CF = сброшен, если операция прошла успешно
(AX = дескриптор файла (file handle))
DS:EDX -> полное имя временного файла.
CF = установлен, если произошла ошибка
(AX = код ошибки)
3.3 РАСШИРЕННЫЕ ФУНКЦИИ ПОДДЕРЖКИ МЫШИ
WDOSX расширяет возможности следующих функций прерывания INT 33H:
AX = 0009H - Задать форму графического курсора
AX = 000CH - Установка обработчика прерываний от мыши
(Custom Event Handler)
AX = 0016H - Сохранить состояние драйвера мыши
AX = 0017H - Восстановить состояние драйвера мыши
0009H - Задать форму графического курсора
AX = 0009H
ES:EDX -> указатель на битмап формы курсора
BX = номер позиционирующего столбца в битмапе
(hot spot column)
CX = номер позиционирующей строки в битмапе
(hot spot row)
000CH - Установка обработчика прерываний от мыши
AX = 000CH
ES:EDX -> дальний (FAR) указатель на обработчик мыши
CX = маска вызова обработчика (см. оригинальный INT33h/0Ch)
Примечание:
Вызов данной функции с адресом 0000:00000000 приведет к
деактивации (uninstall) ранее установленного обработчика.
0016H - Сохранить состояние драйвера мыши
AX = 0016H
ES:EDX -> адрес буфера для сохранения
BX = размер буфера
0017H Восстановить состояние драйвера мыши
AX = 0017H
ES:EDX -> адрес буфера для сохранения
BX = размер буфера
3.4. ПРОЧИЕ ФУНКЦИИ WDOSX
INT 21H / AX = 0FFFFH "Изменить размер начального блока памяти"
Вход:
AX = 0FFFFH
EDX = новый размер блока в байтах
Выход:
CF = сброшен, если операция
прошла успешно, при этом размер блока
изменен, и селекторы переустановлены
CF = установлен в случае ошибки
Примечание:
Эта функция необходима в связи с тем,
что программа, работающая с DPMI,
не может самостоятельно изменить размер
блока памяти, в котором она сама выполняется.
Однако, функцию не рекомендуется выполнять
изнутри HLL кода, поскольку задействованные
в программе библиотеки самостоятельно следят
за выделением необходимой для их работы памяти,
что может вызвать конфликт при изменении
размеров основного блока памяти.
INT 31H / AX = EEFFH "Идентификация DOS экстендера"
Вход:
AX = EEFFh
Выход:
CF = сброшен
EAX = 'WDSX'
ES:EBX = дальний указатель на ASCIIZ
строку с копирайтами
CH = метод выделения памяти
(0=INT15, 1=XMS, 2=VCPI, 3=DPMI)
CL = тип процессора (3=386, 4=486, ... )
DH = старшие цифры версии экстендера
( в данный момент = 0 )
DL = младшие цифры версии экстендера
( в данный момент 94 )
Примечание:
Поскольку данная функция поддерживается
большинством существующих DOS экстендеров,
она может служить удобным средством определения,
под каким именно экстендером запущена программа.
ПЛАНЫ НА БУДУЩЕЕ
Перечислю только самые первые пункты из моего списка пожеланий:
1. Задействовать действительно плоскую модель памяти (True flat model)
(с нулевым базовым адресом) для прочих перемещаемых форматов исполняемых
файлов (в т.ч. PE формат), такую же, как вариант WDOSX для WATCOM.
Главной сложностью на этом пути является обеспечение обратной совместимости
с предыдущими версиями. Однако, не-перемещаемые форматы, такие как MZ или
"flat form binary" никогда не будут вызываться с дескрипторами с нулевым
базовым адресом, поскольку просто не существует способа перемещать такие
исполняемые модули.
2. Улучшение Win32 эмулятора. Это улучшение может включать
или не включать поддержку DLL, плюс возможность для пользователя
добавлять новые функции для эмуляции.
Это достаточно трудная задача, поскольку потребуется привести исходный
код эмулятора Win32 в удобочитаемый вид, чтобы выпустить его как релиз.
3. Изменение в Британском законодательстве, чтобы разрешить публичным
домам быть открытыми после 11 часов, если (и только если) у них имеется
в продаже пиво Radeberger (клевая вещь! ;)
Вот, собственно, и всё. Успехов!
Wuschel a.k.a Michael Tippach
Рустам Гадеев, 15 May 98
|