Dos fn 62h дать адрес psp


Содержание

MS-DOS для программиста

3.3. Префикс программного сегмента PSP

Префикс программного сегмента всегда создается при загрузке программы в память и имеет следующий формат:

Программы могут получить из PSP такую информацию, как параметры командной строки при запуске, размер доступной памяти. Зная адрес PSP, легко найти сегмент области переменных среды и получить другую полезную информацию.

Формат PSP

Формат блока PSP и описание назначения всех его полей приведены ниже:

Смещение, байт Размер, байт Имя поля Описание
2 int20h Двоичный код команды INT 20h (программы могут использовать эту команду для завершения своей работы)
2 2 mem_top Нижняя граница доступной памяти в системе в параграфах
4 1 reserv1 Зарезервировано
5 5 call_dsp Команда CALL межсегментного вызова диспетчера MS-DOS
10 4 term_adr Адрес завершения (Terminate Address)
14 4 cbrk_adr Адрес обработчика прерывания, который получает управление, если пользователь нажал комбинацию клавиш
18 4 crit_err Адрес обработчика критической ошибки
22 2 parn_psp Сегмент PSP программы, запустившей данную программу (программы-родителя)
24 20 file_tab Таблица открытых файлов; если в этом поле находятся байты 0FFH, то таблица не используется
44 2 env_seg Сегмент блока памяти, содержащего переменные среды
46 4 ss_sp Адрес стека программы SS:SP
50 2 max_open Максимальное количество открытых файлов
52 4 file_tba Адрес таблицы открытых файлов
56 24 reserv2 Зарезервировано
80 3 disp Диспетчер функций MS-DOS
83 9 reserv3 Зарезервировано
92 16 fcb1 Если первый аргумент командной строки содержит правильное имя файла, поле форматируется как стандартный блок FCB
108 20 fcb2 Заполняется для второго аргумента командной строки аналогично fcb1
128 1 p_size Количество значащих символов в неформатированной области параметров, либо буфер обмена с диском DTA , назначенный по умолчанию
129 127 parm Неформатированная область параметров, заполняется при запуске программы из командной строки

Для обращения к полям PSP мы определим тип данных PSP:

Используя поле parn_psp, можно определить адрес PSP родительской программы, то есть программы, запустившей вашу программу.

Поле term_adr содержит значение, полученное из таблицы векторов прерываний для прерывания INT 22h. Это адрес программы, которая получает управление, когда текущая программа завершает свою работу. Такой программой может быть, например, программа command.com .

Ваша программа может определить функцию, которая будет получать управление при завершении ее работы. Для этого она должна записать свой собственный адрес в ячейку таблицы векторов прерываний, соответствующую прерыванию INT 22h, а затем запустить другую программу. Поле term_adr блока PSP запущенной программы будет содержать адрес родительской программы. Когда основная программа завершит свою работу, MS-DOS восстановит адрес программы завершения в векторе прерывания INT 22h из поля term_adr блока PSP.

Поле cbrk_adr содержит адрес программы обработки прерывания, которое возникает, когда пользователь нажимает комбинацию клавиш . При запуске программы этот адрес переписывается из ячейки таблицы векторов прерываний, соответствующей прерыванию INT 23h .

Программа может устанавливать свою собственную функцию обработки прерывания по комбинации клавиш . Поэтому при завершении работы программы MS-DOS восстанавливает оригинальное значение из поля cbrk_adr.

Поле crit_err предназначено для восстановления содержимого вектора прерывания INT 24h (адреса обработчика критических ошибок).

Способы переназначения векторов будут приведены в главе, посвященной прерываниям .

Конечно, программы, составленные на языке С, не обязательно должны использовать PSP для доступа к параметрам командной строки и переменным среды. Для этого есть параметры функции main и набор функций типа getenv, putenv и т. п., предназначенных для работы со средой. Но блок PSP содержит и другую информацию, доступ к которой с помощью стандартных функций невозможен.

Определение адреса PSP

Как программе определить адрес своего PSP ?

Очень просто сделать это в программах, составленных на языке ассемблера: при запуске программы адрес PSP передается ей через регистры DS и ES. То есть этот адрес равен DS:0000 или ES:0000 (для com-программ на PSP указывают также регистры CS и SS).

Программам, составленным на языке С, доступна глобальная переменная _psp типа unsigned int. Эта переменная содержит сегментный адрес PSP .

Программа PARM

В качестве примера приведем текст программы PARM (листинг 3.2), составленной на языке ассемблера, которая выводит на экран передаваемые ей через PSP параметры запуска.

Листинг 3.2. Файл parm\ parm.asm

Для трансляции и редактирования программы PARM вы можете использовать пакетный файл, приведенный в листинге 3.3.

Листинг 3.3. Файл parm\mk.bat

Программа PSPLIST

Программа PSPLIST (листинг 3.4), составленная на языке С, определяет адрес своего блока PSP , затем показывает содержимое некоторых полей PSP.

Описание алгоритма программы. Данная программа производит распечатку основных полей своего PSP

Данная программа производит распечатку основных полей своего PSP. Для этого префикс программного сегмента представим в виде следующей структуры:

byte ret_op[2]; /* команда INT 20h */

word end_of_mem; /* вершина доступной памяти*/


byte old_call_dos[5]; /* старый вызов DOS */

void *term_ptr; /* адрес завершения */

void *ctrlbrk_ptr; /* адрес обработчика Ctrl+Break */

void *criterr_ptr; /* адрес обработчика крит.ошибок */

word father_psp; /* PID родителя */

byte JFT[20]; /* таблица файлов программы */

word env_seg; /* адрес окружения */

void *stack_ptr; /* адрес стека */

word JFT_size; /* размер таблицы файлов */

byte *JFT_ptr; /* адрес таблицы файлов */

byte new_call_dos[3]; /* новый вызов DOS */

Поле ret_op используется для возможного завершения программы по команде RET 0, поле old_call_dos, содержит команду вызова диспетчера функций DOS. Обращение к этому полю в программе может использоваться вместо команды INT 21h, но в современных версиях DOS для этих целей лучше обращаться к полю new_call _dos.

Поле end_of_mem содержит сегментный адрес конца доступной памяти в системе. В три поля: term_ptr, ctrlbrk_ptr, criterr_ptr DOS при загрузке программы копирует содержимое векторов прерываний: 22h, 23h, 24, представляющее собой адреса обработчиков: завершения программы, комбинации клавиш Ctrl+Break, критической ошибки — соответственно. Предполагается, что программа может свободно перенаправить эти векторы на собственные обработчики соответствующих ситуаций, но от забот по восстановлению векторов программа избавляется, так как при ее завершении DOS сама восстанавливает векторы из соответствующих полей PSP завершаемой программы. Для аналогичных целей предназначено и поле stack_ptr — в нем сохраняется (а при завершении — из него восстанавливается) адрес стека, использовавшегося до вызова программы. Поле, именуемое father_psp, содержит сегментный адрес PSP родителя — программы, запустившей данную программу, обычно родителем является COMMAND.COM.

При загрузке программы DOS, кроме программного сегмента, создает для нее еще и сегмент окружения. Сегмент окружения содержит ASCIIZ-строки, задающие значения некоторых глобальных переменных, эти значения могут устанавливаться командой DOS SET, они доступны командным файлам и — через PSP — программам. Набор строк окружения заканчивается пустой ASCIIZ-строкой (нулем). В DOS 3.0 и выше за ним следует еще 2-байтное число строк вызова (обычно 1) и далее — строка (или строки) вызова программы. Обычно в первую (до строк вызова) часть порождаемой программы копируется содержимое окружения программы-родителя. Программа имеет доступ к своему сегменту окружения через поле env_seg PSP, содержащее сегментный адрес окружения.

Поле JFT (Job File Table — Таблица Файлов Задачи) представляет собой массив из 20 однобайтных элементов. При открытии программой файла DOS формирует для него блок-описатль в системной таблице файлов и помещает ссылку на него (его номер) в свободный элемент JFT. Дескриптор файла, возвращаемый программе DOS при открытии файла, является номером элемента в JFT. При запуске программы первые пять элементов создаваемой для нее JFT содержат ссылки на системные файлы, остальные свободны. При обработке JFT DOS использует не прямое обращение к полю JFT PSP, а косвенное — через поле JFT_ptr, а в качестве ограничителя размера JFT — не константу 20, а значение поля JFT_size PSP.

После всего, сказанного выше, не составляет труда написать программу, осуществляющую форматный вывод своего префикса программного сегмента. Для в начале необходимо определить версию DOS (с помощью функции get_DOS_version_h() и получить адрес PSP (с помощью функции addr_PSP()).

Функция get_DOS_version_h() определяет старшее число номера версии DOS, используя для этого функцию DOS 30h (прерывание 21h), которая возвращает в регистре AL старшее число номера версии, а в регистре AH — младшее число. Нас интересует только значение регистра AL.

Функция addr_PSP() возвращает сегментный адрес PSP путем использования функции DOS 62h:

Выход: BX = сегментный адрес PSP текущего процесса

Программирование в среде однозадачной операционной системы

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное учреждение

высшего профессионального образования

«ПЕНЗЕНСКАЯ ГОСУДАРСТВЕННАЯ ТЕХНОЛОГИЧЕСКАЯ АКАДЕМИЯ

Е.В. Грачева

Системное программное обеспечение

Персональных ЭВМ

доктор технических наук, пофессор

зав.кафедрой «Вычислительные машины и системы»

доктор технических наук, пофессор

кафедры «Информационно-вычислительные системы»


Пензенского государственного университета

Грачева Е.В.

Системное программное обеспечение персональных ЭВМ:

Учебнле пособие /Е.В. Грачева – Пенза

Учебное пособие подготовлено на кафедре «Вычислительные машины и системы»

Пензенской государственной технологической академиии и предназначено для студентов высших учебных заведений,обучающихся поспециальности 230101.

Программирование в операционной среде

Операционной средой называется набор функций ОС, сервисов и правила обращения к ним. Поскольку каждая операционная система имеет свой набор функций и правил обращения к ним, программирование в операционной среде каждой ОС должно рассматриваться отдельно [1].

Программирование в среде однозадачной операционной системы

Программы для MS DOS могут быть одного из двух форматов: COM или EXE.

Программы типа COM не могут быть размером более 64 Кб и состоят только из одного сегмента – сегмента кода.

Размер программы типа EXE может превышать 64 кб.

В современных операционных средах приложения пользуются системными вызовами, число которых превышает 2000, в то время как в MS-DOS подобных функций гораздо меньше.

Главным входом большинства функций DOS служит прерывание, вызываемое с помощью команды INT 21h. Параметры функциям DOS передаются через регистры микропроцессора: AX (AH и AL), BX, CX, DX; регистровые пары DS:DX и ES:BX используются в основном при передаче адреса ячейки памяти. Через эти же регистры возвращаются результат работы функции DOS, кроме того могут быть установлены флаги в регистре флагов.

Как и любая операционная система, DOS загружает и выполняет программы. При загрузке программы в начале отводимого для нее блока памяти (для СОМ-программ это вся свободная на данный момент память) создается структура данных PSP (префикс программного сегмента) размером 256 байт (100h). Затем DOS создает копию текущего окружения для загружаемой программы, помещает полный путь и имя программы в конец окружения, заполняет поля PSP следующим образом:

+00h: слово – CDh 20h – команда INT 20h. Если СОМ-программа завершается командой RETN, управление передается на эту команду.

+02h: слово – сегментный адрес первого байта после области памяти, выделенной для программы

+04h: байт – не используется DOS

+05h: 5 байт – 9Ah F0h FEh 1Dh F0h – команда CALL FAR на абсолютный адрес 000C0h, записанная так, чтобы второй и третий байты составляли слово, равное размеру первого сегмента для СОМ-файлов (в этом примере FEF0h). Введено для совместимости с командой СР/М CALL 5.

+0Ah: 4 байта – адрес обработчика INT 22h (выход из программы)

+0Eh: 4 байта – адрес обработчика INT 23h (обработчик нажатия Ctrl-Break).

+12h: 4 байта – адрес обработчика INT 24h (обработчик критических ошибок)

+16h: слово – сегментный адрес PSP процесса, из которого был запущен текущий.

+18h: 20 байт – JFT – список открытых идентификаторов, один байт на идентификатор, FFh – конец списка.

+2Ch: слово – сегментный адрес копии окружения для процесса.

+2Eh: 2 слова – SS:SP процесса при последнем вызове INT 21h.

+32h: слово – число элементов JFT (по умолчанию 20).

+34h: 4 байта – дальний адрес JFT (по умолчанию PSP:0018).

+38h: 4 байта – дальний адрес предыдущего PSP.

+3Ch: байт – флаг, указывающий, что консоль находится в состоянии ввода 2-байтного символа.


+3Dh: байт – флаг, устанавливаемый функцией В711h прерывания 2Fh (при следующем вызове INT 21h для работы с файлом имя файла будет замечено на полное).

+3Eh: слово – не используется в DOS.

+40h: слово – версия DOS, которую вернет функция DOS 30h (DOS 5.0+).

+42h: 12 байт – не используется в DOS.

+50h: 2 байта – CDh 21h – команда INT 21h.

+54h: 7 байт – область для расширения первого FCB (FCB, FileControlBlok — это метод работы с файлами, являющийся рудиментом от ранних версий DOS’а. При его использовании можно работать только с файлами в текущем каталоге, причем даже нет возможности сменить каталог (точнее, даже понятия «каталог» в момент создания этих функций вообще не было). Современные программы эти функции не используют. MS-DOS обеспечивает две технологии обслуживания файлов. Первая была разработана при создании версий 1.Х. Эта технология основана на использовании структур данных, называемых блоками управления файлом (FCB). В то время подавляющее большинство компьютеров работало под управлением операционной системы CPM. Блоки FCB обеспечивали совместимость файлов MS-DOS с файлами этой системы. При разработке MS-DOS версий 2.Х, когда была предложена иерархическая структура организации файлов, была разработана вторая технология их обслуживания. Она основана на использовании ссылок на управляющую запись файла и не требует организации FCB. После того, как эта технология была опробована на операционной системе UNIX, она получила широкое распространение.).

+5Ch: 16 байт – первый FCB, заполняемый из первого аргумента командной строки.

+6Ch: 16 байт – второй FCB, заполняемый из второго аргумента командной строки.

+7Ch: 4 байта – не используется в DOS.

+80h: 128 байт – командная строка и область DTA по умолчанию.

Затем DOS записывает программу в память, начиная с адреса PSP:0100h.

Если загружается ЕХЕ-программа, использующая дальние процедуры или сегменты данных, DOS модифицирует эти команды так, чтобы используемые в них сегментные адреса соответствовали сегментным адресам, которые получили эти процедуры и сегменты данных при загрузке программы в память.

При запуске СОМ-программы регистры устанавливаются следующим образом:

AL = FFh, если первый параметр командной строки содержит неправильное имя диска (например, z:/something), иначе – 00h.

АН = FFh, если второй параметр содержит неправильное имя диска, иначе 00h.

CS = DS = ES = SS = сегментный адрес PSP.

SP = адрес последнего слова в сегменте (обычно FFFEh; меньше, если не хватает памяти).

При запуске ЕХЕ-программы регистры SS:SP устанавливаются в соответствии с сегментом стека, определенным в программе, затем в любом случае в стек помещается слово 0000h и выполняется переход на начало программы (PSP:0100h для СОМ, собственная точка входа для ЕХЕ).

Все эти действия выполняет одна функция DOS – DOS 4Bh – загрузить и выполнить программу. В качестве параметров этой функции передаются:

AL = 00h – загрузить и выполнить;

AL = 01h – загрузить и не выполнять;

DS:DX – адрес ASCIZ-строки с полным именем программы
ES:BX – адрес блока параметров ЕРВ:

+00h: слово – сегментный адрес окружения, которое будет скопировано для нового процесса (или 0, если используется текущее окружение)
+02h: 4 байта – адрес командной строки для нового процесса
+06h: 4 байта – адрес первого FCB для нового процесса
+0Ah: 4 байта – адрес второго FCB для нового процесса
+0Eh: 4 байта – здесь будет записан SS:SP нового процесса после его завершения (только для AL = 01)
+12h: 4 байта – здесь будет записан CS:IP (точка входа) нового процесса после его завершения (только для AL = 01)

AL = 03h – загрузить как оверлей;
DS:DX – адрес ASCIZ-строки с полным именем программы
ES:BX – адрес блока параметров:

+00h: слово – сегментный адрес для загрузки оверлея
+02h: слово – число, которое будет использовано в командах, использующих непосредственные сегментные адреса, – обычно то же самое число, что и в предыдущем поле. 0 для СОМ-файлов

AL = 05h – подготовиться к выполнению (используется в ОС MS DOS начиная с версии 5.0 и выше)
DS:DX – адрес следующей структуры:

+00h: слово – 00h
+02h: слово:

бит 0 – программа – ЕХЕ
бит 1 – программа – оверлей

+04h: 4 байта – адрес ASCIZ-строки с именем новой программы
+08h: слово – сегментный адрес PSP новой программы
+0Ah: 4 байта – точка входа новой программы
+0Eh: 4 байта – размер программы, включая PSP

CF = 0, если операция выполнена, ВХ и DX модифицируются,
CF = 1, если произошла ошибка, АХ = код ошибки (2 – файл не найден, 5 – доступ к файлу запрещен, 8 – не хватает памяти, 0Ah – неправильное окружение, 0Bh – неправильный формат).

Как уже отмечалось, прерывание INT 21h (сервис DOS) служит главным входом большинства функций DOS. Программа, запрашивающая сервис DOS, должна подготовить всю необходимую информацию в регистрах и управляющих блоках, указать в регистре AH номер желаемой функции DOS и затем вызвать прерывание INT 21H.


В таблице 1 приведены функции прерывания INT 21h.

Таблица 1 -Функции прерывания INT21h

Не нашли то, что искали? Воспользуйтесь поиском:

Лучшие изречения: Для студентов недели бывают четные, нечетные и зачетные. 9438 — | 7438 — или читать все.

Dos fn 62h: дать адрес psp

Итак, поскольку вопросы по запуску ДОСа не прекращаются, я решил создать отдельную тему.
Для того, чтобы запускать приложения старой персоналки нам необходимо:

Подсоединяем ЗЫЗ к компу, синхронизируем. Запускаем SeiPSPTool.
Name: Пишем DosBox
PBP file: указываем EBOOT.PBP от DosBox’а
PSP Unit: Диск PSP
Давим Generate.

Теперь переходим на диск ЗЫЗы, PSP/GAME/DOSBOX. Там должен находиться файл dosbox.conf,
если его там нет, скопируйте его туда из папки с ДосБоксом на компе. Открываем dosbox.conf
на диске ЗЫЗы. Гоним курсор в самый низ.

Там такие строчки:
[autoexec]
# Lines in this section will be run at startup.
mount c ms0:/psp

c:
cd civrus
civ.exe

Усё, Теперь раскрываем архив с цивилизацией на нашу ЗЫЗу в папку /PSP/
Отсоединяем ЗЫЗ от компа, на ЗЫЗе заходим в стик, запускаем ДосБокс, и.
Через несколько секунд Civilization нам предлагают выбрать тип монитора.

Полную раскладку 102 клавиш можно найти здесь: http://www.niwra.nl/psp/p-sprint-c/doc/
В разделе The default Keymap написано как переключать между группами клавиш и какие комбинации
каким клавишам соответствуют. Переводить не вижу смысла ибо там и так всё понятно.

По данной схеме вы можете запустить любое другое Дос-приложение, в том числе и приложения
защищенного режима DPMI. Мне доподленно не известно поддерживается ли VCPI, но учитывая что есть
поддержка EMS — это вероятно.

ЗЫ. Я писал это без ЗЫЗы под рукой, так что могут быть неточности. Вечером проверю и поправлю, если что.
В принципе, всё должно работать.

ЗЫЗЫ. Есть ещё эмулятор х86 Bochs, его пользовать сложнее, его описание я размещу позже, если конечно меня никто не опередит.

Dos fn 62h: дать адрес psp

Связь с администрацией сайта:

Среди толпы я одинок

  • Вы здесь:
  • Home >
  • Блог >
  • Документация и курсы >
  • Самоучитель по ассемблеру >
  • Глава 18 — практика: работа с файлами, перехват и восстановление прерываний

Глава 18 — практика: работа с файлами, перехват и восстановление прерываний

  • Written by Administrator
  • Tagged under АссемблерAssemblerСамоучитель по ассемблеру
  • Print

Замечание! Это пожалуй самая большая глава! информация представленная в ней в принципе довольно важна! К сожалению при работе в NT/Windows 2000/XP вам не удастся опробовать пример! Тут нужен чистый DOS, или хотя бы Win9x! Я например воспользуюсь эмулятором!

Работа с файлами через описатели

Если программы, написанные на языках высокого уровня могут открыть файл без выполнения подготовительных действий (они выполняются автоматически), то ассемблерные программы должны создать специальные области данных, которые используются при операциях ввода/вывода. Используется два метода доступа к файлам: метод управляющего блока файла (FCB) и метод дескриптора файла. С помощью метода FCB можно получить доступ только к файлам, находящимся в текущем каталоге. Метод дескриптора файла позволяет получить доступ к любому файлу, независимо от того, какой каталог является текущим.
Начиная с DOS версии 2.0, в набор функций прерывания 21h включе-ны UNIX-подобные файловые функции. Идея их состоит в том, что, когда программа открывает файл, DOS возвращает 16-битовое значение «описателя файла» (дескриптора файла) (handle). После этого, когда программа читает, позиционирует, пишет или закрывает файл, она ссылаетесь на него через описатель. Одно из самых больших удобств – то, что можно обращаться к некоторым устройствам так, как будто это дисковые файлы, через зарезервированные описатели DOS:

Ниже приведен перечень наиболее часто используемых функций пре-рывания 21h для работы с файлами через описатели.
Функция 3cH
Создать файл.
Вход. AH=3ch
DS:DX=адрес строки ASCIIZ с именем файла
CX=атрибут файла
Выход. AX=код ошибки, если CF установлен и описатель файла,
если ошибки нет.
Описание. Файл создается в указанном (или умалчиваемом) оглав-лении и открывается в режиме доступа «чтение/запись». Если файл уже существует, то при открытии файл усекается до нулевой длины. Если атрибут файла – «только чтение», открытие отвергается (атрибут можно изменить функцией 43H).
Функция 5bH
Создать новый файл (не должен существовать).
Вход. AH=5bh
DS:DX=адрес строки ASCIIZ с именем файла
CX=атрибут файла
Выход. AX=код ошибки, если CF установлен и описатель файла,
если ошибки нет
Описание. Этот вызов идентичен функции 3ch, с тем исключением, что он вернет ошибку, если файл с заданным именем уже существует.
Функция 5aH
Создать уникальный файл.
Вход. AH=5ah
DS:DX=адрес строки ASCIIZ с путем (заканчивается \)
CX=атрибут файла
Выход. AX=код ошибки, если CF установлен и описатель файла,
если ошибки нет
DS:DX (не изменяется) становится полным
ASCIIZ-именем нового файла.
Описание. Открывает (создает) файл с уникальным именем в оглав-лении, указанном строкой ASCIIZ, на которую указывает DS:DX. Описа-ние пути должно быть готово к присоединению в его конец имени файла. Необходимо обеспечить минимум 12 байт в конце строки. После возврата строка DS:DX будет дополнена именем файла. DOS создает имя файла из шестнадцатеричных цифр, получаемых из текущих даты и времени. Ес-ли имя файла уже существует, DOS продолжает создавать новые имена, пока не получит уникальное имя.
Функция 3dH
Открыть файл.
Вход. AH=3dh
DS:DX=адрес строки ASCIIZ с именем файла
AL=режим открытия
Выход. AX=код ошибки, если CF установлен и описатель файла,
если ошибки нет
Описание. В момент открытия файл должен существовать. Файл открывается в выбранном режиме доступа (AL = 0 – для чтения; AL = 1 – для записи; AL = 2 – для чтения и записи) и указатель «чтения/записи» ус-танавливается в 0.
Функция 3eH
Закрыть файл.
Вход. AH=3eh
BX=описатель файла
Выход. AX= код ошибки, если CF установлен
Описание. BX содержит описатель файла (handle), возвращенный при открытии. Файл, представленный этим описателем, закрывается, его буфер сбрасываются, а оглавление обновляется корректными размером, временем и датой.
Функция 41H
Удалить файл.
Вход. AH=41h
DS:DX=адрес строки ASCIIZ с именем файла
Выход. AX=код ошибки, если CF установлен
Описание. Имя файла не может содержать обобщенные символы («?» и «*»). Файл удаляется из заданного оглавления заданного диска. Если файл имеет атрибут только чтение, то перед удалением необходимо изме-нить этот атрибут через функцию 43H.
Функция 42H
Установить указатель чтения/записи (можно также узнать размер файла).
Вход. AH=42h
BX=описатель файла
CX:DX=смещение указателя: (CX * 65536) + DX
AL=0 переместить к началу файла + CX:DX
AL=1 переместить к текущей позиции + CX:DX
AL=2 переместить к концу файла — CX:DX
Выход. AX=код ошибки, если CF установлен
DX:AX=новая позиция указателя файла (если нет
ошибки)
Описание. Перемещает логический указатель чтения/записи к нужному адресу, с которого начнется очередная операция чтения или за-писи. Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX:AX. DX здесь старшее значащее слово: действительная длина (DX * 65536) + AX.
Функция 3fH
Читать из файла/устройства.
Вход. AH=3fh
BX=описатель файла
DS:DX=адрес буфера для чтения данных
CX=число считываемых байт
Выход. AX=код ошибки, если CF установлен
AX=число действительно прочитанных байт
Описание. CX байт данных считываются из файла или устройства с описателем, указанным в BX. Данные читаются с текущей позиции указателя чтения/записи файла и помещаются в буфер вызывающей програм-мы, адресуемый через DS:DX.
Всегда необходимо сравнивать возвращаемое значение AX (число прочитанных байт) с CX (запрошенное число байт):
1) если AX=CX, (и CF сброшен) – чтение было корректным без ошибок;
2) если AX=0 – достигнут конец файла (EOF);
3) если AX
Функция 40H
Писать в файл/устройство.
Вход. AH=40h
BX=описатель файла
DS:DX=адрес буфера, содержащего данные
CX=число записываемых байт
Выход. AX=код ошибки, если CF установлен
AX=число действительно записанных байт
Описание. CX байт данных записывается в файл или на устройство с описателем, заданным в BX. Данные берутся из буфера, адресуемого через DS:DX и записываются, начиная с текущей позиции указателя чтения/записи файла. Необходимо всегда сравнивать возвращаемое значение AX (число записанных байт) с CX (запрошенное число байт для записи): если AX = CX, запись была успешной; если AX
Некоторые функции в качестве параметра используют атрибут файла. Атрибут — это один байт битовых флагов, связанный с каждым файлом и находящийся в элементе оглавления для файла. В атрибуте определены следующие биты:
x x A D V S H R
R- только чтение (нельзя обновлять или удалять);
H- скрытый;
S- системный;
V- метка тома;
D- элемент подоглавления;
A- архивный;
x- не используются.
ASCIIZ строка, содержащая имя файла, имеет вид:

«‘d:\путь\имя_файла’,0»

Если диск и/или путь опущены, они принимаются по умолчанию. После вызова функции описатель файла должен быть сохранен для последующих операций. Количество описателей в системе регламентируется файлом CONFIG.SYS.
Приведенный ниже пример иллюстрирует процесс работы с файлом через описатели в ассемблерной программе.

;Создание файла
MOV AH,3CH
MOV CX,0
LEA DX,BUF ;DS:DX – адрес ASCIIZ строки с именем
INT 21H
JC NO_CREATE ;Проверка флага переноса
. . . ;Работа с файлом
NO_CREATE:
. . .
BUF DB ‘d:\Users\1.txt’,0

Работа с файлами через DTA

Как было сказано ранее, используются два метода доступа к файлу: метод управляющего блока файла (FCB) и метод дескриптора файла. В любом случае программа при работе с файлами должна указывать место в памяти, куда будут помещаться принимаемые данные или откуда будут извлекаться выводимые. Обычно временный буфер устанавливается раз-мером в одну запись и бывает удобно описать его как строковую переменную в сегменте данных.
Буфер, используемый методом FCB доступа к файлам, называется областью обмена с диском или DTA. На этот буфер указывает условный указатель, который хранится операционной системой и который может быть изменен программой. В документации этот указатель на DTA часто сам называют DTA. Указатель на DTA устанавливается специальной функцией DOS и после того как он установлен все функции чтения/записи автоматически обращаются к нему. Это означает, что сами функции не должны содержать адрес временного буфера.
Для установки указателя на DTA используется функцию 1AH прерывания 21H (DS:DX должны указывать на первый байт DTA). Функция 2FH прерывания 21H сообщает текущую установку указателя DTA (при возврате ES:BX содержат сегмент и смещение DTA).
Префикс программного сегмента PSP обеспечивает каждую программу 128-байтным встроенным DTA, начиная со смещения 80H и до 9FH. Программа может использовать его при нехватке памяти. Первоначально указатель на DTA указывает именно на этот буфер, поэтому если программа будет использовать его, то нет нужды устанавливать указатель. Этот буфер по умолчанию особенно удобно использовать с COM файлами, где DS указывает на начало префикса программного сегмента. Для файлов EXE может потребоваться небольшой добавочный код, чтобы использовать DTA по умолчанию.

Примечание: после извлечения года к нему необходимо прибавить 1980.
Существует ряд функций для работы с файлами, используя DTA. Наиболее употребимые из них приведены ниже.
Функция 1ah
Установить адрес DTA.
Вход. AH=1aH
DS:DX=адрес для DTA
Выход. Нет
Описание. Устанавливает адрес DTA.
Функция 2fh
Дать текущий DTA.
Вход. AH=2fH
Выход. ES:BX=адрес для DTA
Описание. Возвращает адрес начала области ввода-вывода (DTA). Поскольку DTA глобальна для всех процессов, в рекурсивной процедуре (например, при проходе по дереву оглавления) может потребоваться со-хранить адрес DTA, а впоследствии восстановить его посредством функ-ции 1aH.
Функция 4eh
Найти 1-й совпадающий файл.
Вход. AH=4eH
DS:DX=адрес строки ASCIIZ с именем файла
CX=атрибут файла для сравнения
Выход. AX=код ошибки, если CF установлен
DTA=заполнена данными (если не было ошибки)
Описание. DS:DX указывает на строку ASCIIZ в форме: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они подразумевают-ся по умолчанию. Обобщенные символы * и ? допускаются в имени файла и расширении. DOS находит имя первого файла в оглавлении, которое совпадает с заданным именем и атрибутом, и помещает найденное имя и другую информацию в DTA.
Функция 4fh
Найти следующий совпадающий файл.
Вход. AH=4fH
DS:DX= адрес данных, возвращенных предыдущей 4eH.
Выход. AX=код ошибки, если CF установлен
DTA=заполнена данными (если не было ошибки)
Описание. DS:DX указывает на 2bH-байтовый буфер с информаци-ей, возвращенной функцией 4eH (либо DTA, либо буфер, скопированный из DTA).Необходимо использовать эту функцию после вызова 4eH. Сле-дующее имя файла, совпадающее по обобщенному имени и атрибуту фай-ла, копируется в буфер по адресу DS:DX вместе с другой информацией (см. функцию 4eH о структуре файловой информации в буфере, заполняе-мом DOS).
Ниже приведен фрагмент программы, иллюстрирующий организацию поиска файлов в текущем каталоге.

;Установить адрес DTA
MOV AH,01AH
LEA DX,FDTA
INT 21H
. . .
;Наити первый совпадающий файл
MOV AH,4EH
LEA DX,MASKA
MOV CX,10H
INT 21H
JC EXIT
NEXT:
. . .
;Найти следующий совпадающий файл
MOV AH,4FH
MOV CX,10H
LEA DX,MASKA
INT 21H
JNC NEXT
EXIT:
. . .
;========== DTA =========
FDTA DB 15H DUP (?)
FATTR DB ?
FTIME DW ?
FDATA DW ?
FSIZE DD ?
FNAME DB 0DH DUP (‘$’)
;========================
MASKA DB ‘*.*’,0

Структура PSP

Префикс программного сегмента PSP (Program Segment Prefics) – специальная область оперативной памяти размером 256 (100h) байт. PSP может использоваться в программе для определения имен файлов и пара-метров из командной строки, введенной при запуске программы на выпол-нение, объема доступной памяти, переменных окружения системы и так далее. После загрузки программы в память сегментные регистры DS и ES указывают на начало PSP этой программы.

Окружение DOS

DOS поддерживает область памяти, содержащую набор строк ASCIIZ, которые могут использоваться приложениями для получения некоторой системной информации и для передачи данных между программами. Эта область памяти называется окружением DOS.
Структура окружения DOS:

имя_1=значение_1«0»
имя_2=значение_2«0»
. . .
имя_N=значение_N«0»
«0»
«xxxx»
EXEC_string_1«0»
. . .
EXEC_string_NN«0»
«0»

Здесь «0» — это символ ASCII NUL (00H), а «xxxx» — 16-битовое дво-ичное значение (количество дополнительных строк).
Окружение не превышает 32K байт и начинается на границе парагра-фа. Смещение 2cH в PSP текущей программы содержит номер параграфа окружения. Используя окружение, можно найти нужное имя’ серией срав-нений строк ASCIIZ, пока не достигнута пустая строка (нулевой длины), что указывает конец окружения.
В последних версиях DOS, за концом официального окружения по-мещается дополнительная строка, которая содержит диск и путь, с которых была загружена программа. Вслед за последней строкой ASCIIZ окруже-ния находится нулевой байт, указывающий конец официального окруже-ния. Следующие два байта содержат 16-битовый двоичный счетчик допол-нительных строк (обычно 0001H). Вслед за значением счетчика находится строка ASCIIZ, содержащая путь и имя файла. Это в точности та строка, которая использовалась функцией DOS 4bH (EXEC) для загрузки и запуска программы.

Работа с прерываниями

Иногда необходимо выполнить одну из набора специальных проце-дур, если в системе или в программе возникают определенные условия, например, нажата клавиша на клавиатуре. Действие, стимулирующее вы-полнение одной из таких процедур, называется прерыванием. Существует два общих класса прерываний: внутренние и внешние. Первые иницииру-ются состоянием ЦП или командой, а вторые — сигналом, подаваемым от других компонентов системы.
Переход к процедуре прерывания осуществляется из любой програм-мы, а после выполнения процедуры прерывания обязательно происходит возврат в прерванную программу. Перед обращением к процедуре преры-вания должно быть сохранено состояние всех регистров и флагов, исполь-зуемых процедурой прерывания, а после окончания прерывания эти реги-стры должны быть восстановлены.
Последовательность прерывания состоит в следующем:
1) текущее значение регистра Flags включается в стек;
2) текущее значение регистра CS включается в стек;
3) текущее значение регистра IP включается в стек;
4) сбрасываются флаги IF и TF.
Новое содержимое IP и CS определяет начальный адрес выполняемой процедуры прерывания (обслуживание прерывания). Возврат в прерван-ную программу осуществляется командой, которая извлекает из стека со-держимое для IP, CS и регистра флагов (обычно это команда IRET).
Адреса подпрограмм обслуживания прерываний (вектора прерыва-ний) хранятся в таблице векторов прерываний. Таблица векторов прерыва-ний располагается по адресу 0000:0000 и представляет собой массив из 256 элементов, каждый элемент которого занимает 4 байта и представ-ляет собой начальный адрес процедуры обработки прерывания.
Иногда в программе возникает необходимость переопределения (пе-рехвата) прерываний (например, выполнение дополнительных действий при нажатии определенной клавиши клавиатуры). Процесс перехвата пре-рываний состоит в следующем:
1) подготавливается FAR-процедура – новый обработчик прерыва-ний (должна заканчиваться командой IRET);
2) сохраняется старый вектор прерывания (функция 35h прерывания 21h)
3) адрес нового обработчика заносится в таблицу векторов прерыва-ний (функция 25h прерывания 21h);
4) в конце программы происходит восстановление первоначального обработчика прерываний.
Функция 35h
Вход. AH=35H
AL=номер прерывания (00H до 0ffH)
Выход. ES:BX=адрес обработчика прерывания
Описание. Возвращает значение вектора прерывания для INT (AL),
то есть загружает в BX 0000:[AL*4], а в ES –
0000:[(AL*4)+2].
Функция 25h
Вход. AH=25H
AL=номер прерывания (00H до 0ffH)
DS:DX=вектор прерывания (адрес подпрограммы)
Выход. Нет
Описание. Устанавливает значение элемента таблицы векторов прерываний для прерывания с номером AL равным DS:DX. Это равно-сильно записи 4-байтового адреса в 0000:(AL*4), но, в отличие от прямой записи, в момент записи прерывания будут заблокированы.

Разбор практической программы

Задание: Создать текстовый файл «Dir.Txt», содержащий перечень файлов в текущем каталоге. Написать программу переопределения прерывания 05h (клавиша Print Screen).
Примечание:
1) файл «Dir.txt» можно создавать через описатели;
2) получение пути по которому была запущена программа (первая строка в файле «Dir.Txt») можно осуществить, используя окружение DOS. Для этого, во-первых, необходимо получить адрес PSP (функция 062H прерывания 21H), во-вторых, найти в нем адрес окружения DOS. В-третьих, получив из окружения DOS строку, содержащую путь и имя за-пущенного файла, выделить из нее путь к текущему каталогу;
3) на следующем этапе производится поиск первого совпадающего с маской «*.*» файла и его имя записывается в файл «Dir.Txt». Перед на-чалом поиска необходимо правильно установить атрибут файла в CX для сравнения. Далее производится поиск следующего совпадающего с маской файла, используя функцию 04FH прерывания 21H. Если такой файл най-ден, то его имя записывается в «Dir.Txt», иначе осуществляется выход из программы;
4) перед загрузкой нового вектора прерывания необходимо сохранить старый вектор (функция 35h прерывания 21h);
5) новый обработчик прерывания должен быть FAR-процедурой;
6) для проверки, новая процедура обработки прерывания 05h должна выводить в динамик сигнал (прерывание 21H). В основной программе не-обходимо организовать большой цикл, например, выводящий на экран символы (прерывание 21h использовать нельзя, можно использовать, на-пример, прерывание 10h). Таким образом, при нажатии на PrintScreen во время этого цикла компьютер должен издавать сигнал.

Файл fandp.asm
.model tiny
.186
.code
;благодаря этой директиве мы сразу имеем адрес окружения! :) удобно! :)
org 2Ch
okr dw ?
org 100h
start:
;так можно загрузить сегм. регистр! :)
push okr
pop es
;начали искать строку с именем в окружении DOS
xor ax,ax
xor di,di
cld
met:scasb
jne d
cmp es:[di+1],byte ptr 0
je quit
d:jmp met
quit:add di,2
xor si,si
ms:mov al,byte ptr es:[di]
cmp al,0
je poka
mov path[si],byte ptr al
inc si
inc di
jmp ms
;закончили сканировать окружение в поисках пути
;перехватываем прерывание
poka:sub si,9
mov ax,3505h
int 21h
mov word ptr oldint, bx
mov word ptr oldint+2,es
mov ax,2505h
mov dx,offset inter
int 21h
;выдаем писк! :) а то принт скрин всё равно нажать не успеем! :)
int 5h
mov ah,0h
int 16h
lea dx,mesg
mov ah,9
int 21h
;открываем файл
call openfile
mov handle,ax
mov ah,40h
mov bx,handle
mov cx,si
lea dx,path
int 21h
mov ah,40h
mov bx,handle
mov cx,2
lea dx,crlf
int 21h
;установить адрес dta
mov ah,01ah
lea dx,fdta
int 21h
;начать поиск файлов
mov ah,4eh
lea dx,maska
mov cx,10h
int 21h
jc exit
mov di,0
mov cx,14
m0:cmp fname[di],’0′
je h0
inc di
h0:loop m0
mov ah,40h
mov bx,handle
mov cx,di
lea dx,fname
int 21h
mov ah,40h
mov bx,handle
mov cx,2
lea dx,crlf
int 21h
next:mov ah,4fh
mov cx,10h
lea dx,maska
int 21h
jc exit
mov di,0
mov cx,14
m2:cmp fname[di],’0′
je h1
inc di
h1:loop m2
mov ah,40h
mov bx,handle
mov cx,di
lea dx,fname
int 21h
mov ah,40h
mov bx,handle
mov cx,2
lea dx,crlf
int 21h
xor ax,ax
mov di,0
mov cx,14
m1:mov fname[di],al
inc di
loop m1
jmp next
exit: mov ah,3eh
mov bx,handle
int 21h
;восстанавливаем вектор обратно
mov ax,2505h
mov dx,word ptr oldint+2
mov ds,dx
mov dx,word ptr cs:oldint
int 21h
ret
;процедура обработки прерывания
inter proc far
pusha
push es
push ds
mov dl,07
mov ah,02
int 21h
pop ds
pop es
popa
jmp cs:oldint
inter endp
;процедура открытия файла
openfile proc near
mov ah,3ch
mov cx,0
mov dx,offset buf
int 21h
jnc nerr
mov dx,offset myerr
mov ah,9
int 21h
;перевод строки
mov dx,offset crlf
mov ah,09h
int 21h
nerr: ret
openfile endp
;.
oldint dd ?
mesg db «Find files$»
crlf db 0Dh,0Ah,’$’
buf db «filedir»,0
myerr db «WARNING.
File not create$»
handle dw ?
maska db «*.*»,0
fdta db 15h dup (?)
fattr db ?
ftime dw ?
fdata dw ?
fsize dd ?
fname db 14 dup (‘0’)
path db 256 dup (?)
end start

Компиляция :
c:\specprog\tasm\bin\tasm.exe /m fandp.asm
c:\specprog\tasm\bin\tlink.exe fandp.obj /t/x

Вот что имеем в результате запуска:
(под эмулятором и на реальном DOS при запуске вы услышите «писк»)
список найденых файлов сохраняется в файле filedir


Dos fn 62h: дать адрес psp

Плохо смотрел значит, там все что нужно есть, даже больше чем тебе сейчас нужно знать

═══════════════════════════════════ ════════════════════╡ Функции DOS │
DOS Fn 00H: Завершить программу
DOS Fn 01H: Ввод с клавиатуры
DOS Fn 02H: Вывод на дисплей
DOS Fn 03H: Ввод AUX
DOS Fn 04H: Вывод AUX
DOS Fn 05H: Вывод на принтер
DOS Fn 06H: Обмен с консолью
DOS Fn 07H: Нефильтрующий консольный ввод без эха
DOS Fn 08H: Консольный ввод без эха
DOS Fn 09H: Выдать строку
DOS Fn 0aH: Буферизованный ввод строки
DOS Fn 0bH: Проверить статус ввода
DOS Fn 0cH: Ввод с очисткой
DOS Fn 0dH: Сбросить диск
DOS Fn 0eH: Выбрать умалчиваемый диск DOS
DOS Fn 0fH: Открыть файл через FCB
DOS Fn 10H: Закрыть файл через FCB
DOS Fn 11H: Найти 1-й совпадающий файл через FCB
DOS Fn 12H: Найти следующий совпадающий файл через FCB
DOS Fn 13H: Удалить файл через FCB
DOS Fn 14H: Читать последовательный файл через FCB
DOS Fn 15H: Писать последовательный файл через FCB
DOS Fn 16H: Создать файл через FCB
DOS Fn 17H: Переименовать файл через FCB
DOS Fn 19H: Дать умалчиваемый диск DOS
DOS Fn 1aH: Установить адрес DTA
DOS Fn 1bH: Дать информацию FAT (текущий диск)
DOS Fn 1cH: Дать информацию FAT (любой диск)
DOS Fn 21H: Читать запись произвольного файла
DOS Fn 22H: Писать запись произвольного файла
DOS Fn 23H: Дать размер файла через FCB
DOS Fn 24H: Установить адрес блока произвольного файла
DOS Fn 25H: Установить вектор прерывания
DOS Fn 26H: Создать префикс программного сегмента
DOS Fn 27H: Читать блок произвольного файла
DOS Fn 28H: Писать блок произвольного файла
DOS Fn 29H: Разобрать имя файла
DOS Fn 2aH: Дать дату DOS
DOS Fn 2bH: Установить дату DOS
DOS Fn 2cH: Дать время DOS
DOS Fn 2dH: Установить время DOS
DOS Fn 2eH: Установить/сбросить переключатель верификации
DOS Fn 2fH: Дать текущий DTA
DOS Fn 30H: Дать номер версии DOS
DOS Fn 31H: Завершиться и остаться резидентным — KEEP
DOS Fn 32H: Дать дисковую информацию DOS (недокументировано)
DOS Fn 33H: Установить/опросить уровень контроля прерывания DOS
DOS Fn 34H: Адрес статуса реентерабельности DOS
DOS Fn 35H: Дать вектор прерывания
DOS Fn 36H: Дать свободную память диска
DOS Fn 37H: Установить/опросить символ-переключатель (недокументировано)
DOS Fn 38H: Дать/Установить информацию страны
DOS Fn 39H: Создать новое оглавление — MKDIR
DOS Fn 3aH: Удалить оглавление — RMDIR
DOS Fn 3bH: Установить умалчиваемое оглавление DOS — CHDIR
DOS Fn 3cH: Создать описатель файла
DOS Fn 3dH: Открыть описатель файла
DOS Fn 3eH: Закрыть описатель файла
DOS Fn 3fH: Читать файл через описатель
DOS Fn 40H: Писать в файл через описатель
DOS Fn 41H: Удалить файл
DOS Fn 42H: Установить указатель файла — LSEEK
DOS Fn 43H: Установить/опросить атрибут файла — CHMOD
DOS Fn 44H: Управление вводом-выводом устройства — IOCTL
DOS Fn 45H: Дублировать описатель файла — DUP
DOS Fn 46H: Переназначить описатель — FORCDUP
DOS Fn 47H: Дать умалчиваемое оглавление DOS
DOS Fn 48H: Распределить память (дать размер памяти)
DOS Fn 49H: Освободить блок распределенной памяти
DOS Fn 4aH: Сжать или расширить блок памяти
DOS Fn 4bH: Выполнить или загрузить программу — EXEC
DOS Fn 4cH: Завершить программу — EXIT
DOS Fn 4dH: Дать код выхода программы — WAIT
DOS Fn 4eH: Найти 1-й совпадающий файл
DOS Fn 4fH: Найти следующий совпадающий файл
DOS Fn 54H: Дать переключатель верификации DOS
DOS Fn 56H: Переименовать/переместить файл
DOS Fn 57H: Установить/опросить время/дату файла
DOS Fn 59H: Дать расширенную информацию об ошибке
DOS Fn 5aH: Создать уникальный временный файл
DOS Fn 5bH: Создать новый файл
DOS Fn 5cH: Блокировать/разблокировать доступ к файлу
DOS Fn 5eH: Различные сетевые функции
DOS Fn 5fH: Переназначение устройств в сети
DOS Fn 62H: Дать адрес префикса программного сегмента
═══════════════════════════════════ ════════════════════╡ Прерывания DOS
INT 20H: Завершить программу
INT 21H: Функции DOS
INT 22H: Адрес завершения
INT 23H: Адрес выхода по Ctrl-Break
INT 24H: Обработчик критических ошибок
INT 25H/26H: Прямые дисковые чтение/запись
INT 27H: Завершиться и остаться резидентным
INT 28H: Квант времени DOS (недокументировано)
INT 2eH: Выполнить команду DOS (недокументировано)
INT 2fH: Мультиплексное прерывание

MS-DOS для программиста

3.3. Префикс программного сегмента PSP

Префикс программного сегмента всегда создается при загрузке программы в память и имеет следующий формат:

Программы могут получить из PSP такую информацию, как параметры командной строки при запуске, размер доступной памяти. Зная адрес PSP, легко найти сегмент области переменных среды и получить другую полезную информацию.

Формат PSP

Формат блока PSP и описание назначения всех его полей приведены ниже:

Номер функции Название Входные данные Выходные данные Описание
Функции ввода/вывода данных
01H Ввод с клавиатуры AH = 01H AL = символ, полученный из стандартного ввода Считывает (ожидает) символ со стандартного входного устройства. Отображает этот символ на стандартное выходное устройство (эхо). При распознавании Ctrl-Break выполняется INT 23H. Замечание: Ввод расширенных клавиш ASCII (F1-F12, pgup, курсор и т.п.) требует двух обращений к этой функции. Первый вызов возвращает AL=0. Второй вызов возвращает в AL расширенный код ASCII.
02H Вывод на дисплей AH = 02H DL = символ, выводимый на стандартный вывод Посылает символ из DL на стандартный вывод. Обрабатывает символ Backspace (ASCII 8), перемещая курсор влево на одну позицию и оставляя его в новой позиции. При обнаружении Ctrl-Break выполняется INT 23H.
03H Вспомогательный ввод AH = 03H AL = символ, полученный со стандартного вспомогательного устр-ва Считывает (ожидает) символ со стандартного вспомогательного устройства, COM1 или AUX и возвращает этот символ в AL. Замечание: Ввод не буферизуется и должен опрашиваться (не управляется прерываниями). При запуске DOS порт AUX (COM1) инициализируется так: 2400 бод, без проверки на четность, 1 стоп-бит, 8-битовые слова. Команда DOS MODE используется для установки иных характеристик.
04H Вспомогательный вывод AH = 04H DL = символ, записываемый на стандартное вспомогательное устр-во Посылает символ в DL на стандартное вспомогательное устройство, COM1 или AUX.
05H Вывод на принтер AH = 05H DL = символ, записываемый на стандартный принтер Посылает символ в DL на стандартное устройство принтера, обычно LPT1. Замечание: Команда DOS «MODE» может перенаправить этот вывод в последовательный порт.
06H Консольн. ввод-вывод AH = 06H DL = символ (от 0 до 0feh), посылаемый на стандартный вывод DL = 0ffh запрос ввода со стандартного ввода ZF = Сброшен (NZ), если символ готов при запросе ввода При DL = 0ffh выполняет ввод с консоли «без ожидания», возвращая взведенный флаг нуля (ZF), если на консоли нет готового символа. Если символ готов, сбрасывает флаг ZF (NZ) и возвращает считанный символ в AL. Если DL не равен 0ffh, то DL направляется на стандартный вывод. Замечание: Не проверяет Ctrl-Break. Вызывайте дважды для расширенного ASCII.
07H Нефильтрующий консольный ввод без эха AH = 07H AL = символ, полученный через стандартный ввод Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. Не фильтрует: Не проверяет на Ctrl-Break, backspace и т.п. Замечания Вызывайте дважды для ввода расширенного символа ASCII. Используйте функцию 0bh для проверки статуса (если не хотите ожидать нажатия клавиши).
08H Консольный ввод без эха AH = 08H AL = символ, полученный через стандартный ввод Считывает (ожидает) символ со стандартного входного устройства и возвращает этот символ в AL. При обнаружении Ctrl-Break выполняется прерывание INT 23H. Замечание: Вызывайте дважды для ввода расширенного символа ASCII.
09H Выдать строку на дисплей AH = 09H DS:DX = адрес строки, заканчивающейся символом ‘$’ (ASCII 24H) Строка, исключая завершающий ее символ ‘$’, посылается на стандартный вывод. Символы Backspace обрабатываются как в функции 02H Display Char. Обычно, чтобы перейти на новую строку, включают в текст пару CR/LF (ASCII 0dh и ASCII 0ah). Строки, содержащие ‘$’, можно выдать через 40H Write Handle (BX=0).
0ah Ввод строки в буфер AH = 0ah DS:DX = адрес входного буфера (смотри ниже) Буфер содержит ввод, заканчивающийся символом CR (ASCII 0dh) При входе буфер по адресу DS:DX должен быть оформлен так:
Max * * * *

Где max – максимальная допустимая длина ввода (от 1 до 254)

При выходе буфер заполнен следующим образом:

Max Len T E X T 0dh

Где len– действительная длина данных без завершающего CR (здесь — 04H). Символы считываются со стандартного ввода вплоть до CR (ASCII 0dh) или до достижения длины MAX-1. Если достигнут MAX-1, включается консольный звонок для каждого очередного символа, пока не будет введен возврат каретки CR (нажатие Enter).

Второй байт буфера заполняется действительной длиной введенной строки, не считая завершающего CR. Последний символ в буфере — всегда CR (который не засчитан в байте длины). Символы в буфере (включая LEN) в момент вызова используются как «шаблон». В процессе ввода действительны обычные клавиши редактирования: Esc выдает «\» и начинает с начала, F3 выдает буфер до конца шаблона, F5 выдает «@» и сохраняет текущую строку как шаблон, и т.д. Большинство расширенных кодов ASCII игнорируются. При распознавании Ctrl-Break выполняется прерывание INT 23H (буфер остается неизменным).

0bh Проверить статус ввода AH = 0bh AL = 0ffh, если символ доступен со стандартного ввода Проверяет состояние стандартного ввода. При распознавании Ctrl-Break выполняется INT 23H. Замечание: используйте перед функциями 01H 07H и 08H, чтобы избежать ожидания нажатия клавиши. Эта функция дает простой неразрушающий способ проверки Ctrl-Break в процессе длинных вычислений или другой обработки, обычно не требующей ввода. Это позволяет вам снимать счет по нажатию Ctrl-Break.
0ch Ввод с очисткой AH = 0ch AL = номер функции ввода DOS (01H, 06H, 07H, 08H или 0ah) Очищает буфер опережающего ввода стандартного ввода, а затем вызывает функцию ввода, указанную в AL. Это заставляет систему ожидать ввод очередного символа. Следующие значения допустимы в AL: 01H ввод с клавиатуры 06H ввод с консоли 07H Нефильтрующий без эха 08H ввод без эха 0ah буферизованный ввод
Операции с файлами
3ch Создать файл через описатель (дескриптор) AH = 3ch DS:DX = адрес строки ASCIIZ с именем файла CX = атрибут файла AX = код ошибки если CF установлен и описатель файла если ошибки нет DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Файл создается в указанном (или умалчиваемом) оглавлении Файл открывается в режиме доступа чтение/запись Вы должны сохранить описатель (дескриптор, handle) для последующих операций. Если файл уже существует: При открытии файл усекается до нулевой длины Если атрибут файла — только чтение, открытие отвергается (атрибут можно изменить функцией 43H изменить атрибут) CONFIG.SYS специфицирует число доступных описателей в системе Используйте функцию 5bh создать Новый файл, если вы не хотите перекрывать (усекать) существующий файл.
3dh Открыть описатель файла AH = 3dh DS:DX = адрес строки ASCIIZ с именем файла AL = режим открытия AX = код ошибки если CF установлен и описатель файла если нет ошибки. DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Файл должен существовать. См. Функцию 3ch (создать файл). Файл открывается в выбранном режиме доступа / режиме открытия для совместимости с DOS 2.x и избежания сетевых режимов, задавайте: AL = 0 чтобы открыть для чтения AL = 1 чтобы открыть для записи AL = 2 чтобы открыть для чтения и записи Указатель чтения/записи устанавливается в 0. См. 42H (LSEEK) Вы должны сохранить описатель (handle) для последующих операций Разделение файлов должно быть активизировано (команда DOS SHARE), если запрашивается открытие в одном из режимов разделения. CONFIG.SYS специфицирует число доступных описателей файлов.
3eh Закрыть описатель файла AH = 3eh BX = описатель файла AX = код ошибки если CF установлен BX содержит описатель файла (handle), возвращенный при открытии. Файл, представленный этим описателем, закрывается, его буфера сбрасываются, и оглавление обновляется корректными размером, временем и датой. Из-за нехватки описателей файлов (максимум 20, по умолчанию 8), вам может понадобиться закрыть часть умалчиваемых описателей, как, например, описатель 3 (стандартный AUX).
3fh Читать файл через описатель AH = 3fh BX = описатель файла DS:DX = адрес буфера для чтения данных CX = число считываемых байт AX = код ошибки если CF установлен или число действительно прочитанных байт CX байт данных считываются из файла или устройства с описателем, указанным в BX. Данные читаются с текущей позиции указателя чтения/записи файла и помещаются в буфер вызывающей программы, адресуемый через DS:DX. Используйте функцию 42H LSEEK, чтобы установить указатель файла, если необходимо (OPEN сбрасывает указатель в 0). Модифицирует указатель чтения/записи файла, подготавливая его к последующим операциям чтения или записи. Вы должны всегда сравнивать возвращаемое значение AX (число прочитанных байт) с CX (запрошенное число байт): Если AX = CX, (и CF сброшен) — чтение было корректным без ошибок Если AX = 0, достигнут конец файла (EOF) Если AX При чтении с устройства — входная строка имеет длину AX байт При чтении из файла — в процессе чтения достигнут EOF Замечания: Эта функция превосходит сложные и неудобные FCB-функции. Она эффективно сочетает произвольный и последовательный доступ, позволяя пользователю выполнять свое собственное блокирование. Удобно использовать эту функцию для чтения стандартных описателей, таких как описатели стандартного в/в, взамен многочисленных буферизующих и посимвольных FCB-функций ввода. Когда вы читаете с устройства, AX возвращает длину считанной строки с учетом завершающего возврата каретки CR (ASCII 0dh).
40H Писать в файл через описатель AH = 40H BX = описатель файла DS:DX = адрес буфера, содержащего записываемые данные CX = число записываемых байт AX = код ошибки если CF установлен AL = число реально считанных байт (лучший тест для ошибок) CX байт данных записывается в файл или на устройство с описателем, заданным в BX. Данные берутся из буфера, адресуемого через DS:DX. Данные записываются, начиная с текущей позиции указателя чтения/записи файла. Используйте функцию 42H LSEEK, чтобы установить указатель файла, если необходимо (OPEN сбрасывает указатель в 0). Обновляет указатель чтения/записи файла, чтобы подготовиться к последующим операциям последовательного чтения или записи. Вы должны всегда сравнивать возвращаемое значение AX (число записанных байт) с CX (запрошенное число байт для записи). Если AX = CX, запись была успешной Если AX Замечание: Эта функция превосходит сложные и неудобные FCB-функции. Она эффективно сочетает произвольный и последовательный доступ, позволяя пользователю осуществлять собственное блокирование. Удобно использовать эту функцию для вывода на умалчиваемые устройства, такие как стандартный вывод, взамен использования различных функций вывода текста.
42H Установить указатель файла – LSEEK AH = 42H BX = описатель файла CX:DX = на сколько передвинуть указатель: (CX 65536) + DX AL = 0 переместить к началу файла + CX:DX AL = 1 переместить к текущей позиции + CX:DX AL = 2 переместить к концу файла + CX:DX AX = код ошибки если CF установлен DX:AX = новая позиция указателя файла (если нет ошибки) Перемещает логический указатель чтения/записи к нужному адресу. Очередная операция чтения или записи начнется с этого адреса. Замечание: Вызов с AL=2, CX=0, DX=0 возвращает длину файла в DX:AX. DX здесь старшее значащее слово: действительная длина (DX 65536) + AX.
Операции с файловой системой
0dh Сброс диска AH = 0dh Сбрасывает (пишет на диск) все файловые буфера. Если размер файла изменился, такой файл должен быть предварительно закрыт (при помощи функций 10H или 3eh).
0eh Установить текущий диск DOS AH = 0eh DL = номер диска (0=A, 1=B и т.д.), который становится текущим AL = общее число дисководов в системе Диск, указанный в DL, становится текущим (умалчиваемым) в DOS. Проверка: используйте функцию 19H «дать текущий» для проверки. В регистре AL возвращается число дисководов всех типов, включая твердые диски и «логические» диски (как B: в 1-floppy системе).
19H Дать текущий диск DOS AH = 19H AL = номер текущего умалчиваемого диска (0=A, 1=B, и т.д.) Возвращает номер дисковода текущего умалчиваемого диска DOS.
1bh Дать информацию FAT (текущий диск) AH = 1bh DS:BX = адрес байта FAT > Возвращает информацию о размере и типе умалчиваемого диска. Размер диска в байтах = (DX*AL*CX). Ищите свободную память функциями 36h Disk Free или 32h Disk Info. Версии: DOS 1.x держит FAT в памяти и возвращает DS:BX => FAT. DOS 2.0+ может держать в памяти лишь порцию всей FAT. Предупреждение: Эта функция изменяет содержимое регистра DS.
1ch Дать информацию FAT (любой диск) AH = 1ch DL = номер диска (0=текущий, 1=A, и т.д.) DS:BX = адрес байта FAT > Аналогична функции 1bh Get FAT Cur, с той разницей, что регистр DL указывает диск, для которого вы хотите получить информацию. Версии: Недоступна для DOS 1.x.
32H Дать информацию DOS о диске AH = 32H DL = номер диска (0=текущий, 1=A, и т.д.) AL = 0 если DL задавал корректный диск FF = 0ffh если диск задан неверно DS:BX = адрес блока информации диска для запрошенного устройства Возвращает блок информации, представляющей интерес для приложений и утилит, выполняющих доступ к диску, поддерживаемый драйверами устройств, на уровне секторов. Некоторые дисководы (особенно незагружаемые) функционируют исключительно через свои драйверы устройств. Такие диски могут содержать неверную информацию в корневой записи и таблице разделов, что делает очень трудным определение, например, размера корневого оглавления, числа таблиц FAT, и т.п. Блок информации диска содержит все данные такого рода в хорошо форматированной структуре. Это может быть единственным способом определить адрес драйвера устройства. Предупреждение: Изменяет сегментный регистр DS. Эта недокументированная функция может измениться в будущих версиях.
36H Дать свободную память диска AH = 36H DL = номер диска (0=текущий, 1=A, и т.д.) AX = 0ffffh, если AL содержал неверный номер диска или число секторов на кластер, если нет ошибок. BX = доступных кластеров. CX = байт на сектор. DX = всего кластеров на диске. Возвращает данные для подсчета общей и доступной дисковой памяти. Если в AX возвращено 0ffffh, значит, вы задали неверный диск. Иначе, свободная память в байтах = (AX*BX*CX) всего памяти в байтах = (AX*CX*DX)
39H Создать новое оглавление — MKDIR AH = 39H DS:DX = адрес строки ASCIIZ с именем оглавления AX = код ошибки если CF установлен DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяоглавл»,0 если диск и/или корневой путь опущены, то принимаются по умолчанию. Подоглавление создается и связывается с существующим деревом. Если флаг CF установлен при возврате, то AX содержит код ошибки, и оглавление не создается.
3ah Удалить оглавление – RMDIR AH = 3ah DS:DX = адрес строки ASCIIZ с именем оглавления AX = код ошибки если CF установлен DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяоглавл»,0. Если диск и/или корневой путь опущены, то принимаются по умолчанию. Подоглавление удаляется из структуры оглавления. Если флаг CF установлен при возврате, то AX содержит код ошибки, и оглавление не удаляется. Замечание: Оглавление не должно содержать файлов и подоглавлений и не должно быть связано возможными ограничениями DOS (например, не должно быть задействовано в активных командах JOIN или SUBST).
3bh Установить умалчиваемое оглавление DOS – CHDIR AH = 3bh DS:DX = адрес строки ASCIIZ с именем оглавления AX = код ошибки если CF установлен DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяоглавл»,0. Если диск и/или корневой путь опущены, то принимаются по умолчанию. Указанное подоглавление для указанного диска становится текущим (умалчиваемым) оглавлением DOS для этого (или текущего) диска. Если флаг CF установлен при возврате, то AX содержит код ошибки, и текущее оглавление для выбранного диска не изменяется.
41H Удалить файл AH = 41H DS:DX = адрес строки ASCIIZ с именем файла AX = код ошибки если CF установлен DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Имя файла не может содержать обобщенные символы (‘?’ и ‘*’). Файл удаляется из заданного оглавления заданного диска. Если файл имеет атрибут только чтение, то перед удалением необходимо изменить этот атрибут через функцию 43H CHMOD.
43H Установить/опросить атрибут файла – CHMOD AH = 43H DS:DX = адрес строки ASCIIZ с именем файла AL — код подфункции: = 0 — извлечь текущий атрибут файла AL = 1 — установить атрибут файла CX = новый атрибут файла (для подфункции 01H) AX = код ошибки если CF установлен CX = текущий атрибут файла (для подфункции 00H) DS:DX указывает на строку ASCIIZ в формате: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Атрибут файла извлекается или устанавливается, согласно коду в AL. Замечание: Чтобы спрятать оглавление, используйте CX=02H (а не 12H, как вы, возможно, ожидали, см. описание файловой системы FAT, аттрибуты файлов).
45H Дублировать описатель файла – DUP AH = 45H BX = существующий описатель файла AX = новый описатель файла, дублирующий оригинал или код ошибки если CF установлен. Создает дополнительный описатель файла, ссылающийся на тот же поток в/в, что и существующий описатель. Любое продвижение указателя чтения/записи для одного описателя действует на его дубликат — включая любые операции чтения, записи или перемещения указателя посредством функции 42H LSEEK. Новый описатель наследует ограничения режима открытия оригинала. Эта функция используется с одной главной целью: вы можете закрыть описатель, заставляя DOS записать файловые буфера. Такой способ DUP/CLOSE — быстрее, чем закрытие и повторное открытие файла. Оставить комментарий – для сохранения файла без его закрытия – CTRL+S
46H Переназначить описатель – FORCDUP AH = 46H BX = целевой описатель файла (должен уже существовать) CX = исходный описатель файла (должен уже существовать) AX = код ошибки если CF установлен Заставляет описатель файла (handle) ссылаться на другой файл или устройство. Описатель в CX (источник) закрывается, если он открыт, а затем становится дубликатом описателя в BX (назначения). Иными словами, описатели в CX и BX будут ссылаться на один и тот же физический файл или устройство. Используется для переназначения стандартного в/в. Пример: Откроем файл «C:\STDOUT.TXT» через функцию 3dh Open File и получим описатель (например, 05). Установим BX=05, CX=01 и вызовем эту функцию. (замечание: описатель 01 — это предопределенный описатель «стандартного выходного устройства»). Теперь можно вызвать функцию 3eh Close File и закрыть handle 05. Можно обращаться к файлу STDOUT.TXT через описатель 01. Стало быть, дисковый файл «C:\STDOUT.TXT» будет отныне получать весь вывод, создаваемый всеми процессами (текущим и порожденными) через любую функцию символьного в/в DOS, так же как и любой вывод в описатель файла 01 через функцию DOS 40H. Когда вы выходите в COMMAND.COM, предопределенные описатели устанавливаются на обычные устройства (например, описатель 01 устанавливается на «CON»).
47H Дать умалчиваемое оглавление DOS AH = 47H DS:SI = адрес локального буфера для результирующего пути (64 байта) DL = номер диска (0=текущий, 1=A, и т.д.) AX = код ошибка если CF установлен В пользовательский буфер по адресу DS:SI помещается в форме ASCIIZ путь текущего умалчиваемого оглавления для диска, указанного в DL. Путь возвращается в формате: «путь\оглавление»,0. Не подставляется впереди буква диска, а сзади не подставляется символ «\». Например, если текущим является корневое оглавление, эта функция вернет вам пустую строку (DS:[SI] = 0).
4eh Найти 1-й совпадающий файл AH = 4fh DS:DX = адрес строки ASCIIZ с именем файла (допускаются ? И *) CX = атрибут файла для сравнения AX = код ошибки если CF установлен DTA = заполнена данными (если не было ошибки) DS:DX указывает на строку ASCIIZ в форме: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они подразумеваются по умолчанию. Обобщенные символы и ? Допускаются в имени файла и расширении. DOS находит имя первого файла в оглавлении, которое совпадает с заданным именем и атрибутом, и помещает найденное имя и другую информацию в DTA, как показано ниже: Замечания: Атрибут файла обычно используется во «включающем» поиске. Если вас интересуют как файлы, так и оглавления, установите бит атрибута 4 (т.е. Attr | 10H). См. Атрибут файла для полной информации. Типичная последовательность, используемая для поиска всех подходящих файлов: Используйте вызов 1ah, чтобы установить DTA на локальный буфер (или используйте умалчиваемую DTA в PSP по смещению 80H) Уст. CX=атрибут, DS:DX => ASCIIZ диск, путь, обобщенное имя Вызовите функцию 4eh (Найти 1-й) Если флаг CF указывает ошибку, вы закончили (нет совпадений) Уст. DS:DX => DTA (или на данные, которые вы скопировали из DTA после вызова функции 4eh) Повторять Обработать имя файла и данные по адресу DS:DX Вызвать функцию 4fh (Найти следующий) Пока CF=1 не покажет, что совпадений больше нет
4fh Найти следующий совпадающий файл AH = 4fh DS:DX = адрес данных, возвращенных предыдущей 4eh Найти 1-й файл AX = код ошибки если CF установлен DTA = заполнена данными DS:DX указывает на 2bh-байтовый буфер с информацией, возвращенной функцией 4eh Найти 1-й (либо DTA, либо буфер, скопированный из DTA). Используйте эту функцию после вызова 4eh. Следующее имя файла, совпадающее по обобщенному имени и атрибуту файла, копируется в буфер по адресу DS:DX вместе с другой информацией (см. Функцию 4eh о структуре файловой информации в буфере, заполняемом DOS).
56H Переименовать/переместить файл AH = 56H DS:DX = адрес старого ASCIIZ имени (путь/имя существующего файла) ES:DI = адрес нового ASCIIZ имени (новые путь/имя) AX = код ошибки если CF установлен DS:DX и ES:DI указывают на строки ASCIIZ: «d:\путь\имяфайла»,0. Старое имя DS:DX должно отвечать существующему файлу и не может содержать обобщенных символов. Диск и путь необязательны (если опущены, они принимаются по умолчанию). Новое имя ES:DI должно описывать НЕ существующий файл. Если указан диск, он должен быть тем же, что и в старом имени. Если диск или путь опущены, принимаются текущие умолчания. Если старое и новое имя содержат разные пути (явно или принятые по умолчанию), то элемент оглавления для файла ПЕРЕМЕЩАЕТСЯ в оглавление, указанное в новом имени. Замечание: Если ID диска в старом имени отличается от текущего диска DOS, не забывайте указывать такой же ID диска в новом имени.
57H Установить/опросить дату/время файла AH = 57H AL = 0 чтобы получить дату/время файла = 1 чтобы установить дату/время файла BX = описатель файла (handle) CX = (если AL=1) новая отметка времени в формате время/дата файла DX = (если AL=1) новая отметка даты в формате время/дата файла AX = код ошибки если CF установлен CX = отметка времени файла в формате время/дата файла DX = отметка даты файла в формате время/дата файла BX должен содержать описатель открытого файла (см. 3ch или 3dh ). Укажите подфункцию, 0 или 1, в регистре AL. DX и CX задаются в формате памяти; например, младшие 8 бит даты находятся в DH.
5ah Создать уникальный временный файл AH = 5ah DOS 3.0+ DS:DX = адрес строки ASCIIZ с диском и путем (заканчивается \) CX = атрибут файла AX = код ошибки если CF установлен и описатель файла (если нет ошибки) DS:DX = (не изменяется) становится полным ASCIIZ-именем нового файла Открывает (создает) файл с уникальным именем в оглавлении, указанном строкой ASCIIZ, на которую указывает DS:DX. COMMAND.COM использует эту функцию, когда создает временные «канальные» файлы, используемые при переназначении ввода-вывода. Описание пути должно быть готово к присоединению в его конец имени файла. Вы должны обеспечить минимум 12 байт в конце строки. Сама строка должна быть заполнена в одной из форм: «d:\путь\»,0 (указаны диск и путь) ИЛИ «d:»,0 (умалчиваемое оглавление диска) ИЛИ «d:\»,0 (корневое оглавление диска) ИЛИ «»,0 (умалчиваемые диск и оглавление) После возврата строка DS:DX будет дополнена именем файла. Замечания: DOS создает имя файла из шестнадцатеричных цифр, получаемых из текущих даты и времени. Если имя файла уже существует, DOS продолжает создавать новые имена, пока не получит уникальное имя. Создаваемые таким способом файлы — по существу НЕ ВРЕМЕННЫЕ, и их следует удалять посредством функции DOS 41H , когда они не нужны. Версии: Доступна, начиная с DOS 3.0
5bh Создать новый файл AH = 5bh DOS 3.0+ DS:DX = адрес строки ASCIIZ с именем файла CX = атрибут файла AX = код ошибки если CF установлен и описатель файла если ошибок нет DS:DX указывает на строку ASCIIZ в форме: «d:\путь\имяфайла»,0. Если диск и/или путь опущены, они принимаются по умолчанию. Этот вызов идентичен функции DOS 3ch CREATE, с тем исключением, что он вернет ошибку, если файл с заданным именем уже существует. Файл открывается для чтения/записи в совместимом режиме доступа
5ch Блокировать/разблокировать доступ к файлу AH = 5ch DOS 3.0+ AL = подфункция: 0 = заблокировать область файла = 1 = разблокировать ранее захваченную область BX = описатель файла (handle) CX:DX = смещение ((CX 65536) + DX) от начала файла SI:DI = длина блокируемой области ((SI 65536) + DI) байт AX = код ошибки если CF установлен Блокирует или освобождает доступ к участку файла, идентифицируемого описателем в BX. Область файла, начинающаяся по логическому смещению CX:DX и имеющая длину SI:DI, блокируется (захватывается) или разблокируется (освобождается). Смещение и длина обязательны. Разделение файлов ДОЛЖНО быть активизировано (командой SHARE), иначе функция вернет код ошибки «неверный номер функции.» Блокировка действует на операции чтения, записи и открытия со стороны порожденного или конкурирующего процесса. При попытке такого доступа (и режиме доступа , определенном при OPEN как «режим разделения», который запрещает такой доступ), DOS отвергает операцию через вызов INT 24H (обработчик критических ошибок) после трех попыток. DOS при этом выдает сообщение «Abort, Retry, Ignore». Рекомендуемое действие — НЕ пытаться читать файл и ожидать кода ошибки. Вместо этого попытайтесь заблокировать область и действуйте в соответствии с кодом возврата. Это позволяет избежать довольно неустойчивого состояния DOS, связанного с выполнением INT 24H. Блокировка за концом файла не является ошибкой. Вы можете захватить весь файл, задав CX=0, DX=0, SI=0ffffh, DI=0ffffh и AL=0. При освобождении, смещение и длина участка должны точно совпадать со смещением и длиной захваченного участка. Замечания: Дублирование описателя через 45H или 46H дублирует и блокировки. Даже если во время OPEN выбран режим доступа Inherit, механизм блокировки не даст никаких привилегий доступа порожденным процессам, созданным функцией 4bh EXEC (они трактуются как отдельные). Важно, чтобы все блокировки файла были сняты до завершения программы. Если вы используете блокировку, особо отслеживайте вызовы INT 23H (выход Ctrl-Break) и INT 24H (выход по критической ошибке), чтобы снять блокировки до действительного завершения программы. Рекомендуется освобождать блокировки как можно скорее. Всегда блокируйте, обрабатывайте файл и освобождайте блокировку одной операцией. Версии: Доступна, начиная с DOS 3.0
Операции с системой прерываний
25H Установить вектор прерывания AH = 25H AL = номер прерывания DS:DX = вектор прерывания: адрес программы обработки прерывания Устанавливает значение элемента таблицы векторов прерываний для прерывания с номером AL равным DS:DX. Это равносильно записи 4-байтового адреса в 0000:(AL*4), но, в отличие от прямой записи, DOS здесь знает, что вы делаете, и гарантирует, что в момент записи прерывания будут заблокированы. Предупреждение: Не забудьте восстановить DS (если необходимо) после этого вызова.
26H Построить PSP AH = 26H DX = адрес сегмента (параграфа) для нового PSP CS = сегмент PSP, используемого как шаблон для нового PSP Устанавливает PSP для порождаемого процесса по адресу DX:0000. Текущий PSP (100H байт, начиная с CS:0), копируется в DX:0 Поле memtop соответственно корректируется Векторы Terminate, Ctrl-Break и Critical Error копируются в PSP из векторов прерываний INT 22H, INT 23H и INT 24H после этого вы можете загрузить программу с диска и передать ей управление посредством FAR JMP. Замечание: Если вы перехватываете INT 21H, позаботьтесь о помещении в стек корректного CS:IP. Еще лучше использовать функцию 4ch (EXEC).
2ah Дать системную дату AH = 2ah AL = день недели (0=Вск, 1=Пнд. 6=Суб) DOS 3.0+ CX = год (1980 до 2099) DH = месяц (1 до 12) DL = день (1 до 31) Возвращает текущую дату, как она известна системе. Версии: DOS 2.x не гарантирует возврата в AL значения дня; все версии 1.0+ возвращают правильный день недели. Версии до 2.1 имеют проблемы с переходом даты.
2bh Установить системную дату AH = 2bh CX = год (1980 до 2099) DH = месяц (1 до 12) DL = день (1 до 31) AL = 0 если дата корректна Устанавливает системную дату DOS.
2ch Дать время DOS AH = 2ch CH = часы (0 до 23) CL = минуты (0 до 59) DH = секунды (0 до 59) DL = сотые доли секунды (0 до 99) Возвращает текущее время, как оно известно системе. Замечание: Поскольку системные часы имеют частоту 18.2 тиков в секунду (интервал 55мс), DL имеет точность 0.04 сек.
2dh Установить время DOS AH = 2dh CH = часы (0 до 23) CL = минуты (0 до 59) DH = секунды (0 до 59) DL = сотые доли секунды (0 до 99) AL = 0 если время корректно Устанавливает системное время DOS.
2eh Установить/сбросить переключатель верификации AH = 2eh AL = 0 отключить верификацию = 1 включить верификацию Устанавливает, должна ли DOS верифицировать (считывать обратно) каждый сектор, записываемый на диск. Это замедляет операции записи на диск, но гарантирует максимальную надежность записи. Функция 56H Get Verify возвращает текущий статус верификации DOS.
2fh Дать адрес текущей DTA AH = 2fh ES:BX = адрес начала текущей DTA Возвращает адрес начала области ввода-вывода (DTA). Поскольку DTA глобальна для всех процессов, в рекурсивной процедуре (например, при проходе по дереву оглавления) может потребоваться сохранить адрес DTA, а впоследствии восстановить его посредством функции 1ah «Уст. DTA». Замечание: Эта функция изменяет сегментный регистр ES.
30H Дать номер версии DOS AH = 30H AL = старший номер версии AH = младший номер версии BX,CX = 0000H DOS 3.0+ Возвращает в AX значение текущего номера версии DOS. Например, для DOS 3.2, в AL возвращается 3, в AH — 2. Замечание: Если в AL возвращается 0, можно предполагать, что работает DOS более ранней версии, чем DOS 2.0. Версии: DOS 2.x не гарантирует очистки регистров CX и BX.
31H Завершиться и остаться резидентным – KEEP AH = 31H AL = код выхода DX = объем памяти, оставляемой резидентной, в параграфах Выходит в родительский процесс, сохраняя код выхода в AL. Код выхода можно получить через функцию 4dh Wait. DOS устанавливает начальное распределение памяти, как специфицировано в DX, и возвращает управление родительскому процессу, оставляя указанную память резидентной (число байт = DX 16). Эта функция перекрывает функцию INT 27H, которая не возвращает код выхода и неспособна установить резидентную программу, большую 64K.
33H Установить/опросить статус Ctrl-Break AH = 33H AL = 0 чтобы опросить текущий статус контроля Ctrl-Break AL = 1 чтобы установить статус контроля Ctrl-Break DL = требуемый статус (0=OFF, 1=ON) (только при AL=1) DL = текущий статус (0=OFF, 1=ON) Если AL=0, в DL возвращается текущий статус контроля Ctrl-Break. Если AL=1, в DL возвращается новый текущий статус. Когда статус ON, DOS проверяет на Ctrl-Break с консоли для большинства функций (исключая 06H и 07H). При обнаружении, выполняется INT 23H (если оно не перехватывается, то это снимает процесс). Когда статус OFF, DOS проверяет на Ctrl-Break лишь при операциях стандартного в/в, стандартной печати и стандартных операциях AUX.
35H Дать вектор прерывания AH = 35H AL = номер прерывания (00H до 0ffh) ES:BX = адрес обработчика прерывания Возвращает значение вектора прерывания для INT (AL); то есть, загружает в BX 0000:[AL*4], а в ES — 0000:[(AL*4)+2]. Предупреждение: Эта функция изменяет сегментный регистр ES.
44H Управление устройством в/в – IOCTL AH = 43H AL = код подфункции: AL = 0ch — (зарезервировано) Прочие = (в зависимости от подфункции) AX = код ошибки если CF установлен или иное значение (в зависимости от подфункции) IOCTL предоставляет метод взаимодействия с устройствами и получения информации о файлах. Входные параметры и выходные значения варьируются в зависимости от кода подфункции в регистре AL. Версии: Подфункции 0-7 . DOS 2.1+ Подфункции 8,0bh . DOS 3.0+ Подфункции 9,0ah . DOS 3.1+ Подфункции 0dh,0eh,0fh . DOS 3.2+ ———————————— Подфункция 00H: Запросить флаги информации об устройстве Вход: BX= описатель файла (устройство или дисковый файл) Выход: DX= IOCTL Инф об устр ———————————— Подфункция 01H: установить флаги информации об устройстве Вход: BX = описатель файла (устройство или дисковый файл) DX = IOCTL Инф об устр (DH должен быть нулевым) Выход: DX= IOCTL Инф об устр ———————————— Подфункция 02-03: читать (AL=02H) или писать (AL=03H) строку IOCTL на СИМВОЛЬНОЕ устр Вход: DS:DX = адрес буфера (чтение) или данных (запись) CX= число передаваемых байт BX= описатель файла (только устройство — не файл!) Выход: AX= код ошибки если CF установлен ———————————— Подфункция 04-05: читать (AL=04H) или писать (AL=05H) строку IOCTL на БЛОЧНОЕ устр Вход: DS:DX = адрес буфера (чтение) или данных (запись) CX = число передаваемых байт BL = : Вход: CL = код действия 40H = установить параметры устройства 60H = дать параметры устройства 41H = писать дорожку логического устройства 61H = читать дорожку логического устройства 42H = форматировать дорожку с верификацией 62H = Верифицировать дорожку логического устройства DS:DX=> адрес пакета данных IOCTL Выход: AX= код ошибки если CF установлен DS:DX=> пакет данных может содержать информацию возврата. ———————————— Подфункция 0eh: Выяснить, назначил ли драйвер устройства несколько логических устройств одному физическому устройству. [DOS 3.2+] Вход: BL= . Эта функция позволяет вам сообщать DOS, что диск с указанным >
48H Распределить память (дать размер памяти) AH = 48H BX = запрошенное количество памяти в 16-байтовых параграфах AX = код ошибки если CF установлен BX = размер доступной памяти в параграфах (если памяти не хватает) AX = сегментный адрес распределенного блока (если нет ошибок) Распределяет блок памяти длиной BX параграфов, возвращая сегментный адрес этого блока в AX (блок начинается с AX:0000). Если распределение неудачно, устанавливается CF, в AX возвращается код ошибки, а BX содержит максимальный размер доступной для распределения памяти (в параграфах). Чтобы определить наибольший доступный кусок, общепринято устанавливать BX=0ffffh перед вызовом. Распределение завершится с ошибкой, возвратив размер максимального блока памяти в BX. Замечание: Когда процесс получает управление через функцию 4bh EXEC, вся доступная память уже распределена ему.
49H Освободить распределенный блок памяти AH = 49H ES = сегментный адрес (параграф) освобождаемого блока памяти AX = код ошибки если CF установлен Освобождает блок памяти, начинающийся с адреса ES:0000. Этот блок становится доступным для других запросов системы. Вообще говоря, вы должны освобождать лишь те блоки памяти, которые вы получили через функцию 48H распределить память. Родитель отвечает за освобождение памяти порожденных процессов. Тем не менее, ничто не препятствует вам освобождать память чужих процессов.
4ah Сжать или расширить блок памяти AH = 4ah ES = сегмент распределенного блока памяти BX = желаемый размер блока в 16-байтовых параграфах AX = код ошибки если CF установлен BX = наибольший доступный блок (если расширение неудачно) Изменяет размер существующего блока памяти. Когда программа получает управление, функция 4bh EXEC уже распределила блок памяти, начиная с PSP, который содержит всю доступную память. Чтобы освободить память для запуска порождаемых процессов, блок памяти, начинающийся с PSP, необходимо сначала сжать. Замечание: Функция 31H (KEEP) и INT 27H (TSR) сжимают блок по адресу PSP.
4bh Выполнить или загрузить программу – EXEC AH = 4bh DS:DX = адрес строки ASCIIZ с именем файла, содержащего программу ES:BX = адрес EPB (EXEC Parameter Block — блока параметров EXEC) AL = 0 = загрузить и выполнить AL = 3 = загрузить программный оверлей AX = код ошибки если CF установлен Предоставляет средства одной программе (родителю) вызвать другую программу (ребенка), которая по завершению возвратит управление родителю. DS:DX указывает на строку ASCIIZ в форме: «d:\путь\имяфайла»,0. Если диск или путь опущены, они подразумеваются по умолчанию. ES:BX указывает на блок памяти, подготовленный как EPB, формат которого зависит от запрошенной подфункции в AL. AL=0 EXEC: так как родительская программа первоначально получает всю доступную память в свое распоряжение, вы должны освободить часть памяти через функцию 4ah до вызова EXEC (AL=0). Обычная последовательность: 1. Вызовите функцию 4ah с ES=сегменту PSP и BX=минимальному объему памяти, требуемой вашей программе (в параграфах). 2. Подготовьте строку ASCIIZ с именем вызываемого программного файла и установите DS:DX на первый символ этой строки. 3. Подготовьте блок параметров EXEC со всеми необходимыми полями. 4. Сохраните текущие значения SS, SP, DS, ES и DTA в переменных, адресуемых через регистр CS (CS — это единственная точка для ссылок после того, как EXEC вернет управление от ребенка). 5. Выдайте вызов EXEC с AL=0. 6. Восстановите локальные значения SS и SP. 7. Проверьте флаг CF, чтобы узнать, не было ли ошибки при EXEC. 8. Восстановите DS, ES и локальную DTA, если необходимо. 9. Проверьте код выхода через функцию 4dh WAIT (если надо). Все открытые файлы дублируются, так что ребенок может обрабатывать данные как через описатели файлов, так и через стандартный в/в. Режимы доступа описателей дублируются, но любые активные блокировки файлов не будут относиться к ребенку. См. Функцию 5ch. После возврата из ребенка, векторы INT 22H Terminate, INT 23H Ctrl-Break и INT 24H Critical Error восстанавливаются в их предыдущие значения. AL=3 LOAD: Эта подфункция используется для загрузки «оверлея». DS:DX указывает на ASCIIZ имя файла, а ES:BX указывает на «LOAD»-версию блока параметров EXEC. Главное значение этой подфункции в том, что она считывает заголовок EXE и выполняет необходимые перемещения сегментов, как это требуется для программ .EXE. Замечания: Эта функция использует программу-загрузчик из COMMAND.COM, который транзитен в DOS 2.x (и, возможно, уже перекрыт программой). В этом случае возникнет ошибка, если DOS не найдет файл COMMAND.COM. Вы должны обеспечить корректную строку COMSPEC= в окружении перед вызовом этой функции. Вместо разбора собственных FCB (как требуется для EPB), вы можете найти удобным загрузить и выполнить вторичную копию файла COMMAND.COM, используя опцию /C. Например, чтобы выполнить программу FORMAT.COM, установите DS:DX на адрес строки ASCIIZ: «\command.com»,0 и установите EPB+2 на сегмент и смещение следующей строки команд: 0eh,»/c format a:/s/4″,0dh такой вторичный интерпретатор команд использует очень мало памяти (около 4K). Вы можете поискать в окружении DOS строку COMSPEC=, чтобы установить точное местоположение файла COMMAND.COM.
4ch Завершить программу – EXIT AH = 4ch AL = код выхода Возвращает управление от порожденного процесса его родителю, устанавливая код выхода, который можно опросить функцией 4dh WAIT. Управление передается по адресу завершения в PSP завершающейся программы. Векторы Ctrl-Break и Critical Error восстанавливаются к старым адресам, сохраненным в родительском PSP. Замечание: Значение ERRORLEVEL (используемое в пакетных файлах DOS) можно использовать для проверки кода выхода самой последней программы.
4dh Дать код выхода программы – WAIT AH = 4dh AL = код выхода последнего завершившегося процесса AH = 0 — нормальное завершение AH = 1 — завершение через Ctrl-Break AH = 2 — завершение по критической ошибке устройства AH = 3 — завершение через функцию 31H KEEP Возвращает код выхода последнего из завершившихся процессов. Эта функция возвращает правильную информацию только однажды для каждого завершившегося процесса.
54H Дать переключатель верификации DOS AH = 54H AL = 0 если верификация выключена (OFF) AL = 1 если верификация включена (ON) Возвращает текущий статус верификации записи DOS. Если в AL возвращается 1, то DOS считывает обратно каждый сектор, записываемый на диск, чтобы проверить правильность записи. Функция DOS 2eh позволяет установить/изменить режим верификации.
59H Дать расширенную информацию об ошибке AH = 59H DOS 3.0+ BX = 0000H (номер версии: 0000H для DOS 3.0, 3.1 и 3.2) AX = расширенный код ошибки (0, если не было ошибки) BH = класс ошибки BL = предлагаемое действие CH = сфера (где произошла ошибка) Используйте эту функцию, чтобы уточнить, что предпринять после сбоя функции DOS по ошибке (только DOS 3.0+ ). Вызывайте ее: В обработчике критических ошибок INT 24H После любой функции INT 21H , возвратившей Carry-флаг После вызова FCB-функции, возвратившей AL=0ffh Версии: Эта функция отсутствует в версиях до DOS 3.00. В DOS 2.x, когда флаг CF указывает на ошибку, используйте логику вашей программы, чтобы отреагировать на ошибку. В DOS 3.0+, когда функция возвращает CF=1, рекомендуем вам игнорировать код ошибки, возвращенный в AX, вызвать эту функцию и выполнить действие, предложенное в BL.
5eh Разные сетевые функции AH = 5eh DOS 3.1+ AL = подф.: 0=дать имя машины (узла) в сети AL = 2=установить стартовую строку сетевого принтера AL = 3=извлечь стартовую строку сетевого принтера Прочие = (зависят от подфункции) AX = код ошибки если CF установлен Прочие = (зависят от подфункции) Эти функции доступны при установленной IBM PC Network Program. Версии: Доступны, начиная с DOS 3.1 ———————————— Подф. 00H: Извлекает имя машины (узла), как оно известно в сети. Вход: DS:DX=> буфер пользователя для ASCIIZ сетевого имени Выход: DS:DX=> буфер, содержащий сетевое имя CH= 0=имя не определено; иначе=имя определено CL= номер имени NETBIOS (если CH ненулевой) AX= код ошибки если CF установлен Замечание: Сетевое имя — 15-симв. (дополненная пробелами) строка ASCIIZ ———————————— Подф. 02H: Задает настроечную строку, посылаемую на принтер каждый раз, когда эта машина выдает результаты на сетевой принтер. Вход: DS:SI=> буфер, содержащий настроечную строку (до 64 байт) CX= длина настроечной строки BX= индекс в списке назначений, отвечающий принтеру Выход: AX= код ошибки если CF установлен ———————————— Подф. 03H: Извлекает настроечную строку принтера, заданную ранее посредством DOS Fn 5eh подф. 02H. Вход: DS:DI=> 64-байтовый буфер пользователя для результата bx= индекс принтера в списке назначений Выход: ES:DI=> буфер, заполненный настроечной строкой CX= длина настроечной строки AX= код ошибки если CF установлен Замечание: Поскольку индекс в списке назначений может измениться в любой момент, используйте функцию 5fh подф. 02H, чтобы получить индекс непосредственно перед вызовом этой функции.
5fh Переназначение устройств в сети AH = 5fh DOS 3.1+ AL = подф.: 2=получить элемент списка переназначений устройств = 3=переназначить сетевое устройство = 4=отменить переназначение сетевого устройства Прочие = (зависят от подфункции) AX = код ошибки если CF установлен Эти функции доступны при установленной IBM PC Network Program. Версии: Доступны, начиная с DOS 3.1 ———————————— Подф. 02H: Извлекает элемент из списка переназначений сетевых устройств. Вход: DS:DI=> 128-байтовое ASCIIZ локальное имя устр. («LPT1»,0) ES:DI=> 128-байтовый буфер с ASCIIZ сетевым именем BX= индекс в списке назначений Выход: DS:DI=> ASCIIZ локальное имя устройства (напр., «LPT1»,0) ES:DI=> ASCIIZ сетевое имя BL= тип устр: 3=принтер; 04=файл ‘устройство’ BH= статус устр: бит 0=1 -неверное устр.; 0=верное CX= сохраненный параметр (при NETBIOS, всегда 0) AX= код ошибки если CF установлен DX,BP = (изменены) Замечание: обычно эту функцию вызывают с BX=0, затем повторяют вызовы, увеличивая значение BX, пока DOS не вернет ошибку 12H (больше нет файлов). ———————————— Подф. 03H: этот вызов определяет имена оглавлений для сети и перенаправляет доступ на сетевые принтеры. Замеч: доступ к принтеру переназначается на уровне ROM-BIOS INT 17H. Вход: DS:SI = ASCIIZ имя исходного устройства ES:DI = ASCIIZ назначение (сетевой путь с паролем) BL= тип устр: 03=принтер; 04=файл ‘устройство’ CX= параметр для вызывающего (задавайте 0 для NETBIOS) Выход: AX= код ошибки если CF установлен Замеч: если BL=03, то источник задает ASCIIZ-имя принтера (например, «LPT1»,0). Назначение кодируется в форме: [\\computername\],0,[password],0. Если пароль начинается с 00, считается, что пароля нет. Если BL=04, то источник задает ASCIIZ-имя диска (например, «F:»,0), а назначение — ASCIIZ-имя пути. После вызова этой функции, локальные обращения к этому диску переназначаются на выбранные имя компьютера и путь. ———————————— Подф. 04H: Отменить сетевое переназначение для указанного устройства. Вход: DS:SI=> ASCIIZ-имя устройства или ,0), то переназначение этого диска прекращается, и ID диска восстанавливает свое предыдущее значение.
Смещение, байт Размер, байт Имя поля Описание
2 int20h Двоичный код команды INT 20h (программы могут использовать эту команду для завершения своей работы)
2 2 mem_top Нижняя граница доступной памяти в системе в параграфах
4 1 reserv1 Зарезервировано
5 5 call_dsp Команда CALL межсегментного вызова диспетчера MS-DOS
10 4 term_adr Адрес завершения (Terminate Address)
14 4 cbrk_adr Адрес обработчика прерывания, который получает управление, если пользователь нажал комбинацию клавиш
18 4 crit_err Адрес обработчика критической ошибки
22 2 parn_psp Сегмент PSP программы, запустившей данную программу (программы-родителя)
24 20 file_tab Таблица открытых файлов; если в этом поле находятся байты 0FFH, то таблица не используется
44 2 env_seg Сегмент блока памяти, содержащего переменные среды
46 4 ss_sp Адрес стека программы SS:SP
50 2 max_open Максимальное количество открытых файлов
52 4 file_tba Адрес таблицы открытых файлов
56 24 reserv2 Зарезервировано
80 3 disp Диспетчер функций MS-DOS
83 9 reserv3 Зарезервировано
92 16 fcb1 Если первый аргумент командной строки содержит правильное имя файла, поле форматируется как стандартный блок FCB
108 20 fcb2 Заполняется для второго аргумента командной строки аналогично fcb1
128 1 p_size Количество значащих символов в неформатированной области параметров, либо буфер обмена с диском DTA , назначенный по умолчанию
129 127 parm Неформатированная область параметров, заполняется при запуске программы из командной строки

Для обращения к полям PSP мы определим тип данных PSP:

Используя поле parn_psp, можно определить адрес PSP родительской программы, то есть программы, запустившей вашу программу.

Поле term_adr содержит значение, полученное из таблицы векторов прерываний для прерывания INT 22h. Это адрес программы, которая получает управление, когда текущая программа завершает свою работу. Такой программой может быть, например, программа command.com .

Ваша программа может определить функцию, которая будет получать управление при завершении ее работы. Для этого она должна записать свой собственный адрес в ячейку таблицы векторов прерываний, соответствующую прерыванию INT 22h, а затем запустить другую программу. Поле term_adr блока PSP запущенной программы будет содержать адрес родительской программы. Когда основная программа завершит свою работу, MS-DOS восстановит адрес программы завершения в векторе прерывания INT 22h из поля term_adr блока PSP.

Поле cbrk_adr содержит адрес программы обработки прерывания, которое возникает, когда пользователь нажимает комбинацию клавиш . При запуске программы этот адрес переписывается из ячейки таблицы векторов прерываний, соответствующей прерыванию INT 23h .

Программа может устанавливать свою собственную функцию обработки прерывания по комбинации клавиш . Поэтому при завершении работы программы MS-DOS восстанавливает оригинальное значение из поля cbrk_adr.

Поле crit_err предназначено для восстановления содержимого вектора прерывания INT 24h (адреса обработчика критических ошибок).

Способы переназначения векторов будут приведены в главе, посвященной прерываниям .

Конечно, программы, составленные на языке С, не обязательно должны использовать PSP для доступа к параметрам командной строки и переменным среды. Для этого есть параметры функции main и набор функций типа getenv, putenv и т. п., предназначенных для работы со средой. Но блок PSP содержит и другую информацию, доступ к которой с помощью стандартных функций невозможен.

Определение адреса PSP

Как программе определить адрес своего PSP ?

Очень просто сделать это в программах, составленных на языке ассемблера: при запуске программы адрес PSP передается ей через регистры DS и ES. То есть этот адрес равен DS:0000 или ES:0000 (для com-программ на PSP указывают также регистры CS и SS).

Программам, составленным на языке С, доступна глобальная переменная _psp типа unsigned int. Эта переменная содержит сегментный адрес PSP .

Программа PARM

В качестве примера приведем текст программы PARM (листинг 3.2), составленной на языке ассемблера, которая выводит на экран передаваемые ей через PSP параметры запуска.

Листинг 3.2. Файл parm\ parm.asm

Для трансляции и редактирования программы PARM вы можете использовать пакетный файл, приведенный в листинге 3.3.

Листинг 3.3. Файл parm\mk.bat

Программа PSPLIST

Программа PSPLIST (листинг 3.4), составленная на языке С, определяет адрес своего блока PSP , затем показывает содержимое некоторых полей PSP.


8086 Assembly/MS-DOS, передавая имя файла из командной строки

Скажем, у меня есть PROGRAM.ASM. В сегменте данных есть следующее:

Я хочу, чтобы файл file.txt был динамическим, я думаю? После компиляции PROGRAM.exe должен иметь возможность принимать имя файла через командную строку:

Как включить это? Заранее спасибо.

DOS хранит командную строку в старой структуре, называемой префикс сегмента программы («PSP»). И я имею в виду наследие. Эта структура была разработана для обратной совместимости с программами, перенесенными из CP/M.

Вы знаете, как программы, созданные как .COM файлы, всегда начинаются с ORG 100h ? Причина этого в том, что — для программ.COM — PSP всегда хранится в начале сегмента кода (в CS: 0h). PSP имеет длину 0FFh, и фактический программный код начинается сразу после этого (то есть в CS: 100h).

Адрес также удобно доступен в DS: 00h и ES: 00h, поскольку ключевая характеристика формата.COM заключается в том, что все регистры сегментов начинаются с того же значения (а программа COM обычно никогда не меняет их).

Чтобы прочитать командную строку из программы .COM , вы можете выбрать ее длину в CS: 80h (или DS: 80h и т.д., Если вы не изменили эти регистры). Командная строка начинается с CS: 81h и берет оставшуюся часть PSP, заканчивая возвратом каретки (0Dh) в качестве терминатора, поэтому длина командной строки не превышает 126 байтов.

(и поэтому командная строка на DOS оставалась на 126 байт, несмотря на то, что все мы желали в течение многих лет, ее можно было сделать дольше. Поскольку WinNT использует другой механизм доступа к командной строке, WinNT/XP/etc. командной строки не страдает от этого ограничения по размеру).

Для программы .EXE вы не можете полагаться на CS: 00h, потому что сегмент кода запуска может быть примерно где угодно в памяти. Однако, когда программа запускается, DOS всегда сохраняет PSP в базе сегмента данных по умолчанию. Таким образом, при запуске DS: 00h и ES: 00h всегда будут указывать на PSP для программ.EXE и.COM.

Если вы не отслеживали адрес PSP в начале программы, и вы меняли как DS, так и ES, вы всегда можете попросить DOS предоставить значение сегмента в любое время через INT 21h, функцию 62h. Сегментная часть адреса PSP будет возвращена в BX (смещение, конечно, 0h).

Описание алгоритма программы. Данная программа производит распечатку основных полей своего PSP

Данная программа производит распечатку основных полей своего PSP. Для этого префикс программного сегмента представим в виде следующей структуры:

byte ret_op[2]; /* команда INT 20h */

word end_of_mem; /* вершина доступной памяти*/

byte old_call_dos[5]; /* старый вызов DOS */

void *term_ptr; /* адрес завершения */

void *ctrlbrk_ptr; /* адрес обработчика Ctrl+Break */

void *criterr_ptr; /* адрес обработчика крит.ошибок */

word father_psp; /* PID родителя */

byte JFT[20]; /* таблица файлов программы */

word env_seg; /* адрес окружения */

void *stack_ptr; /* адрес стека */

word JFT_size; /* размер таблицы файлов */

byte *JFT_ptr; /* адрес таблицы файлов */

byte new_call_dos[3]; /* новый вызов DOS */

Поле ret_op используется для возможного завершения программы по команде RET 0, поле old_call_dos, содержит команду вызова диспетчера функций DOS. Обращение к этому полю в программе может использоваться вместо команды INT 21h, но в современных версиях DOS для этих целей лучше обращаться к полю new_call _dos.

Поле end_of_mem содержит сегментный адрес конца доступной памяти в системе. В три поля: term_ptr, ctrlbrk_ptr, criterr_ptr DOS при загрузке программы копирует содержимое векторов прерываний: 22h, 23h, 24, представляющее собой адреса обработчиков: завершения программы, комбинации клавиш Ctrl+Break, критической ошибки — соответственно. Предполагается, что программа может свободно перенаправить эти векторы на собственные обработчики соответствующих ситуаций, но от забот по восстановлению векторов программа избавляется, так как при ее завершении DOS сама восстанавливает векторы из соответствующих полей PSP завершаемой программы. Для аналогичных целей предназначено и поле stack_ptr — в нем сохраняется (а при завершении — из него восстанавливается) адрес стека, использовавшегося до вызова программы. Поле, именуемое father_psp, содержит сегментный адрес PSP родителя — программы, запустившей данную программу, обычно родителем является COMMAND.COM.

При загрузке программы DOS, кроме программного сегмента, создает для нее еще и сегмент окружения. Сегмент окружения содержит ASCIIZ-строки, задающие значения некоторых глобальных переменных, эти значения могут устанавливаться командой DOS SET, они доступны командным файлам и — через PSP — программам. Набор строк окружения заканчивается пустой ASCIIZ-строкой (нулем). В DOS 3.0 и выше за ним следует еще 2-байтное число строк вызова (обычно 1) и далее — строка (или строки) вызова программы. Обычно в первую (до строк вызова) часть порождаемой программы копируется содержимое окружения программы-родителя. Программа имеет доступ к своему сегменту окружения через поле env_seg PSP, содержащее сегментный адрес окружения.

Поле JFT (Job File Table — Таблица Файлов Задачи) представляет собой массив из 20 однобайтных элементов. При открытии программой файла DOS формирует для него блок-описатль в системной таблице файлов и помещает ссылку на него (его номер) в свободный элемент JFT. Дескриптор файла, возвращаемый программе DOS при открытии файла, является номером элемента в JFT. При запуске программы первые пять элементов создаваемой для нее JFT содержат ссылки на системные файлы, остальные свободны. При обработке JFT DOS использует не прямое обращение к полю JFT PSP, а косвенное — через поле JFT_ptr, а в качестве ограничителя размера JFT — не константу 20, а значение поля JFT_size PSP.

После всего, сказанного выше, не составляет труда написать программу, осуществляющую форматный вывод своего префикса программного сегмента. Для в начале необходимо определить версию DOS (с помощью функции get_DOS_version_h() и получить адрес PSP (с помощью функции addr_PSP()).


Функция get_DOS_version_h() определяет старшее число номера версии DOS, используя для этого функцию DOS 30h (прерывание 21h), которая возвращает в регистре AL старшее число номера версии, а в регистре AH — младшее число. Нас интересует только значение регистра AL.

Функция addr_PSP() возвращает сегментный адрес PSP путем использования функции DOS 62h:

Выход: BX = сегментный адрес PSP текущего процесса

Dos fn 62h: дать адрес psp

В данной статье рассматривается способ построения резидентных программ — TSR (Terminate and Stay Resident), позволяющий использовать область PSP (Program Segment Prefix) для размещения резидентного кода программы.

Несколько слов о TSR.

При разработке TSR — программ стандартными средствами DOS в памяти после завершения программы остается PSP размером 256 байт или по крайней мере его часть, если программа использует область FCB (File Control Block) и параметров для собственных нужд. Мы расскажем Вам о способе, позволяющем полностью использовать область PSP в интересах резидентной программы и приведем пример такой программы. Данный способ был разработан авторами в начале 1989 года, когда потребовалось загрузить много крохотных TSR — программ, размер которых не превышал PSP.

Кое-что о недокументированных функциях DOS.

Для понимания механизма разработки TSR без PSP необходимо ознакомиться с некоторыми недокументированными функциями DOS и с форматами PSP и MCB — Memory Control Block.

PSP — program segment prefix.

PSP всегда строится DOS при запуске любой программы и непосредственно предшествует началу программы. Рассмотрим формат PSP.

00h 2 БАЙТА содержит команду INT 20h, которая используется для завершения программы 02h СЛОВО сегментный адрес свободной памяти, следующей, за памятью, выделенной программе. Это может быть либо адрес за памятью DOS (например, A000h), либо адрес следующего доступного MCB. 04h БАЙТ Резерв 05h 5 БАЙТ длинный вызов диспетчера функций DOS. Содержит команду длинного перехода к диспетчеру функций DOS. Используется в программах, ориентированных на CP/M. Смещение в команде длинного перехода
содержит количество байтов, доступных в сегменте кода программы. 0Ah ДВ.СЛОВО копия вектора прерывания 22h, по которому управление передается для
завершения программы. 0Eh ДВ.СЛОВО копия вектора прерывания 23h, по которому управление передается при нажатии CONTROL-BREAK или CONTROL-C. 12h ДВ.СЛОВО копия вектора прерывания 24h, по которому управление передается при обнаружении критической ошибки. 16h СЛОВО сегментный адрес PSP родительского процесса (адрес текущего PSP для процесса, у которого нет родителя). 18h 20 БАЙТ FILE HANDLE TABLE. Содержит 20 однобайтовых индексов для системной таблицы файлов. Первые пять входов предназначены для STDIN, STDOUT,STDERR, AUXIO и LSTOUT. 2Ch СЛОВО сегментный адрес блока среды для процесса. 2Eh ДВ.СЛОВО область сохранения указателя стека процесса, когда процесс использует стек DOS (т.е. содержимое SS:SP перед последним подключением функции DOS с помощью INT 21h). 32h СЛОВО максимальное количество входов в FILE HANDLE TABLE (по умолчанию 20). 34h ДВ.СЛОВО адрес FILE HANDLE TABLE (стандартно указывает на таблицу в текущем PSP). 38h 24 БАЙТА Резерв 50h 3 БАЙТА команда INT 21h, за которой следует команда far RET. Используется для вызова диспетчера функций DOS. 53h 2 БАЙТА Резерв 55h 7 БАЙТ расширение первого FCB. 5Ch 16 БАЙТ начальные байты первого неоткрытого FCB. Открытие данного FCB приведет к разрушению второго FCB и байта с длиной командной строки. 6Ch 16 БАЙТ начальные байты второго неоткрытого FCB. Открытие данного FCB приведет к разрушению командной строки. 7Сh ДВ.СЛОВО Резерв 80h 128 БАЙТ область DTA (Data Transfer Area) по умолчанию. Перекрывает байт с длиной командной строки и буфер командной строки (127 байтов).

Размер блока — 256 байт.

MCB — memory control block.

MCB является блоком DOS описывающим каждый распределенный участок памяти. Как правило MCB всегда строится перед PSP исполняемой программы. Рассмотрим формат MCB.

00h БАЙТ тип блока:
‘M’ (4Dh) — промежуточный блок;
‘Z’ (5Ah) — последний блок. 01h СЛОВО сегмент владельца блока, 0 — свободный блок. 03h СЛОВО количество параграфов в блоке. 05h 11 БАЙТ Резерв

Размер блока — 16 байт.

Недокументированные функции DOS.

Рассмотрим теперь недокументированные функции DOS, которые используются для построения TSR без PSP.

установить текущий PSP.

Данная функция указывает DOS, что в качестве текущего следует использовать указанный PSP.

AH = 50h
BX = сегментный адрес нового PSP.

создать подчиненный PSP.

Данная функция требует от DOS создать подчиненный PSP. В отличии от функции 26h данные не копируются из текущего PSP, а строятся заново.

AH = 55h
BX = сегментный адрес для построения нового PSP.
SI = значение, которое требуется установить в поле со смещением 2 в новом PSP.

Процесс завершения резидентной программы.

Сущность завершения резидентной программы без PSP состоит в создании нового PSP и указании DOS использовать этот PSP в качестве активного. При этом сам текст резидентной части перемещается на начало старого PSP.

Рассмотрим последовательность действий при завершении программы.

  1. Освободить ENVIRONMENT, адрес которого находится в PSP по смещению 2Ch. Вообще говоря, это действие не связано с собственно процессом завершения резидентной программы без PSP и рекомендуется для любого способа завершения резидентных программ.
  2. Изменить размер памяти, используемый программой, указав в качестве нового размера длину резидентной части программы в параграфах, а в качестве адреса модифицируемой памяти — сегментный адрес PSP. Для выполнения используется функция DOS 4Ah. Если резидентная часть начинается с начала программы, то ее следует сначала сохранить, т.к. при освобождении памяти в теле программы будет построен новый MCB. Также целесообразно зарезервировать после резидентной части участок длиной 16 байт для MCB, чтобы последующие действия не уничтожили дальнейший код программы.
  3. Вычисляется сегментный адрес для построения нового PSP по формуле + +1 (размер MCB в параграфах).
  4. Строится новый PSP по вычисленному сегментному адресу с использованием функции 55h. В качестве значения SI берется поле со смещением 2 в старом PSP.
  5. Корректируется адрес родительского PSP в новом PSP по смещению 16h. Значение выбирается из поля с таким же смещением из старого PSP.
  6. Новый PSP указывается DOS в качестве текущего с использованием функции 50h.
  7. Корректируется указатель на собственника памяти в новом MCB по смещению 01h. MCB расположен по сегментному адресу равному сегменту нового PSP минус 1. Значение
    указателя устанавливается равным сегментному адресу нового PSP.
  8. Резидентная часть программы пересылается по адресу сегмента старого PSP со смещением 0.
  9. Выполняются необходимые действия для настройки резидентной части. Их можно также выполнить заранее.
  10. Программа завершается обычным образом по функции DOS 04Ch.

Схематически этот метод изображен на 3-х рисунках.

Рисунок 1 показывает изменение в расположении блоков в памяти при выполнении функции DOS 4Ah.

Рисунок 2 показывает изменение в расположении блоков в памяти после выполнения функции DOS 55h и при коррекции указателей.

Рисунок 3 показывает изменение в расположении блоков в памяти после выполнения функции DOS 50h.

Совместимость.

Данный метод опробован в различных совместимых операционных средах:

— MS/PC DOS 3.30;
— MS/PC DOS 4;
— MS DOS 5 beta release;
— DR DOS 3.41;
— DR DOS 5;
— с использованием загрузчика LOADHI от системы QEMM 5.0;
— с использованием загрузки в старшую память HILOAD DR DOS 5.

Пример резидентной программы без PSP.

Для лучшего понимания порядка завершения резидентной программы без PSP приведем пример.

page 60,132
title NONPSP — Резидентная программа без PSP
;==========================================================
;
; Пример построения резидентной программы без PSP
;
; Авторские права ГРУППЫ ПРОГРАММИСТОВ 2B
;
; Язык программирования: Ассемблер
; Транслятор : MASM
;
;===========================================================
;
; сообщить транслятору адресацию
;
assume cs:code,ds:code,es:nothing
;
; определить сегмент кода
;
code segment para
;
subttl Резидентная часть программы
;
ResStart label byte ;определим начало программы

;Текст резидентной части.

ResEnd label byte ;конец резидентной части
ResLen equ ResEnd-ResStart ;размер резидентной части в
; байтах
ResSize equ (ResEnd-ResStart+15)/16 ;размер резидентной
; части в параграфах
org ResStart+ResSize*16 ;для выравнивания на
; границу параграфа
;
page
subttl Инициализация резидентной программы без PSP
;
MCBLen equ 10h ;размер MCB
;
PSPMCB db MCBlen dup (0) ;резервная область для MCB
SavRes db ResLen dup (0) ;область сохранения
; резидентной части
;
PspOld dw 0 ;для адреса старого PSP
PspNew dw 0 ;для адреса нового PSP
;
; сообщения
;
MsgInst label byte
db 0ah,0dh
db ‘Программа установлена’
db 0ah,0dh
db ‘$’
MsgNoInst label byte
db 0ah,0dh
db ‘Ошибка. Программа не установлена’
db 0ah,0dh
db ‘$’
;=========================================================
;
; процедура инициализации резидентной программы без PSP
;
;=========================================================
ini proc far
;
cld ;для операций
пересылки
mov cs:PspOld,ds ;сохраним старый PSP
;
; Освобождение environment
;
mov ax,ds:[2ch] ;адрес сегмента
mov es,ax ; environment
cmp ax,0 ;есть environment ?
je Go1 ; нет
mov ah,49h ;код функции
int 21h ; освободить
; память
jnc Go1 ;успешно
jmp ErrorRet ;неуспешно
Go1:
mov word ptr ds:[2ch],0 ;укажем, что нет
; environment
push cs ;установим
pop es ; ES
push cs ;установим
pop ds ; DS
;
; запомним резидентную часть
; т.к. она будет разрушена при построении новых PSP и MCB
;
mov si,Offset ResStart ;откуда
mov di,Offset SavRes ;куда
mov cx,ResLen ;сколько
rep movsb ;перешлем
;
; модифицируем размер памяти текущей программы от сегмента
; PSP на длину резидентной части
; это приведет к построению нового MCB в теле программы
;
mov ah,4ah ;модифицируем память
mov bx,ResSize ;размер резидентной
; части
mov es,PspOld ;сегмент старого PSP
int 21h ;выполним
jnc Go2 ;успешно
jmp ErrorRet ;неуспешно
Go2:
;
; подсчитаем сегмент памяти для нового PSP
;
mov ax,ResSize ;длина резидентной
; части в параграфах
add ax,PspOld ; плюс сегмент
; старого PSP
add ax,MCBLen/16 ; плюс длина MCB
mov PspNew,ax ;запомним сегмент
; для нового PSP
;
; создадим новый PSP
;
mov es,PspOld ;адрес старого PSP
mov si,word ptr es:[02h] ; конец памяти
mov ah,55h ;построим
; подчиненный PSP
mov dx,PspNew ;сегмент нового PSP
int 21h ;выполним
;
; скорректируем указатель на родительский PSP в новом PSP
;
mov es,PspOld ;сегмент старого PSP
mov ax,word ptr es:[16h] ;адрес родительского
; PSP
mov es,PspNew ;сегмент нового PSP
mov word ptr es:[16h],ax ;скорректируем
;
; сообщим DOS о новом активном PSP
;
mov bx,PspNew ;сегмент нового PSP
mov ah,50h ;функция указания нового PSP
int 21h ; выполним
;
; укажем принадлежность полученной памяти для нового PSP
;
mov ax,bx ;сегмент нового PSP
sub ax,1 ;сегмент
; построенного MCB
mov es,ax
;==================
mov word ptr es:[01h],bx ;скорректируем адрес
; владельца памяти
;
; переместим резидентную часть на старый PSP
;
mov es,PspOld ;адрес старого PSP
mov cx,ResLen ;размер резидентной
; части
mov di,0 ;куда
mov si,Offset SavRes ;откуда
rep movsb ;переместим
push cs ;восстановим
pop es ; ES
;
; Успешный выход из программы
;
PrgEnd:
mov ah,09h ; выведем сообщение
mov dx,offset MsgInst ; об успешной
; установке
int 21h ;
mov ax,4c00h ;завершим программу
int 21h ; обычным
; образом с кодом 0
;
; Выход из программы по ошибке
;
ErrorRet:
push cs ;установим адресацию
pop ds ; данных
mov ah,09h ; выведем сообщение
mov dx,offset MsgNoInst ; о неуспешной
; установке
int 21h ;
mov ax,4c04h ;завершим программу
int 21h ; обычным
; образом с кодом 4
ini endp
;
code ends
;
; СТЕК
;
stack segment stack
dw 512 dup(0)
stack ends
end ini

Илон Маск рекомендует:  Обработка строк в рнр
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL