Дистрибутив операционной системы MS-DOS состоит, в зависимости от версии, из одной или нескольких дискет. На них расположены файлы собственно операционной системы IO.SYS, MSDOS.SYS, командный процессор COMMAND.COM, файлы внешних команд операционной системы (FORMAT, FDISK и т.п.), драйверы и другие файлы.
Файл IO.SYS содержит расширение базовой системы ввода/вывода и является интерфейсом между операционной системой и BIOS. Расширение используется операционной системой для взаимодействия с аппаратурой компьютера и BIOS.
Файл MSDOS.SYS является в некотором смысле набором программ обработки прерываний, в частности прерывания INT 21H. Это тело операционной системы.
Командный процессор COMMAND.COM предназначен для организации диалога с оператором. Он анализирует вводимые оператором команды и организует их выполнение. Так называемые внутренние команды (DIR, COPY и т.д.) обрабатываются именно командным процессором. Программист имеет возможность написать свой собственный командный процессор и подключить его вместо стандартного. Новый командный процессор должен выполнять все функции, которые раньше выполнял стандартный COMMAND.COM.
Драйверы (обычно это файлы, имеющие расширение имени .SYS) представляют собой программы, обслуживающие различную аппаратуру. Эти программы имеют специальный формат и будут подробно описаны в книге. Применение драйверов легко решает проблемы использования новой аппаратуры - достаточно написать для нового устройства драйвер и подключить его к операционной системе. Прикладные программы взаимодействуют с устройствами через драйвер, поэтому они не будут меняться при изменениях в аппаратуре. Например, новое дисковое устройство может иметь другое количество дорожек и секторов, другие управляющие команды. Все это учитывается драйвером, а прикладная программа будет работать с новым диском как и раньше, используя прерывания MS-DOS.
Файлы внешних команд операционной системы содержат программы-утилиты для выполнения разнообразных операций, таких как форматирование дисков, сортировка файлов, печати текстов и других.
Немного об утилитах, предназначенных для подготовки дисков и дискет.
Файлы операционной системы выделяются своим особым расположением на диске (кроме COMMAND.COM) - эти файлы должны находиться в специально отведенном для них месте. Если вам нужно подготовить дискету как системную (т.е. такую, с которой можно загружать операционную систему), для переноса файлов операционной системы следует использовать специальные утилиты.
Самый простой способ подготовки системной дискеты - использовать команду FORMAT с опцией /S, например:
FORMAT A: /S
В этом случае после форматирования на дискету будут перенесены файлы операционной системы. При использовании команды текущим должен быть корневой каталог системного диска, например, диска С:.
Если вы собираетесь обновить версию операционной системы (например, вместо MS-DOS 3.30 установить MS-DOS 4.01), не обязательно заново переформатировать весь диск. Загрузив новую версию с дискеты, для переноса новых системных файлов используйте команду SYS:
SYS C:
Файл COMMAND.COM скопируйте обычным способом.
Если вам надо сделать дискету системной, а ее форматирование нежелательно (дискета содержит важную информацию), воспользуйтесь программой Norton Disk Doctor или аналогичной. Программа освободит место в начале диска для операционной системы, переписав располагавшиеся там данные на свободное место в конце дискеты, затем запишет системные файлы и даже скопирует файл COMMAND.COM.
Утилита FDISK предназначена для подготовки к работе жесткого диска. Она разбивает диск на участки, называемые разделами.
На одном физическом диске могут быть разделы, принадлежащие разным операционным системам. Один из разделов - активный, операционная система загружается из активного раздела.
Для MS-DOS утилита FDISK позволяет создать первичный и вторичный разделы. В первичном разделе располагается системный диск C:, с которого выполняется загрузка операционной системы, вторичный раздел может быть разделен на логические диски (D:, E:, F: и т.д.). Диски, располагающиеся во вторичном разделе, не могут быть системными.
Заметим, что только MS-DOS версии 4.01, 5.0 и Compaq DOS 3.31 позволяют создавать логические диски размером более 32 мегабайт. Это связано с тем, что другие версии DOS используют 16-разрядную адресацию секторов диска, что недостаточно для дисков больших размеров.
Очень часто вместо утилиты FDISK для подготовки жесткого диска используются диск-менеджеры. Это такие программы, как Advanced Disk Manager, Speed Stor и т.д. Используя свои собственные форматы разделов и таблиц разделов (и свои драйверы дисковых устройств), диск-менеджеры предоставляют такие дополнительные возможности, как защита логического диска от записи или организация парольной защиты данных на диске, создание логических дисков размером более 32 мегабайт.
Однако не всегда применение диск-менеджеров может привести к желаемому результату. Защита от несанкционированного доступа часто легко преодолевается, мощные ситемы защиты сильно привязаны к конкретной версии операционной системы (например, WatchDog, очень мощная система защиты, требует только DOS версии 3.20).
Кроме того, драйверы, используемые диск-менеджерами могут замедлить работу дисковой подсистемы компьютера.
Некоторые программы, особенно защищенные от копирования, отказываются работать на диске, подготовленном не утилитой FDISK. Причины этого мы увидим, когда будем обсуждать проблемы защиты программ от несанкционированного копирования.
Перейдем к процедуре начальной загрузки операционной системы.
При включении питания компьютера управление передается базовой системе ввода/вывода, BIOS.Она выполняет проверку аппаратных узлов компьютера, формирует начальную часть таблицы векторов прерываний, инициализирует устройства и начинает процесс загрузки операционной системы.
Загрузка начинается с того, что BIOS делает попытку прочитать самый первый сектор дискеты, вставленной в дисковод А: (на загрузочной дискете этот сектор содержит загрузчик операционной системы). Если в дисковод вставлена системная дискета, с нее считывается загрузчик и ему передается управление.
Если дискета не системная, т.е. не содержит загрузочной записи, на экран выдается сообщение с просьбой заменить дискету.
Если же дискеты в дисководе А: вообще нет, то BIOS читает основную загрузочную запись диска С: (Master Boot Record). Обычно это самый первый сектор на диске. Управление передается загрузчику, который находится в этом секторе. Загрузчик анализирует содержимое таблицы разделов (она также находится в этом секторе), выбирает активный раздел и читает загрузочную запись этого раздела. Загрузочная запись активного раздела (Boot Record) аналогична загрузочной записи, находящейся в первом секторе системной дискеты.
Загрузочная запись активного раздела считывает с диска файлы IO.SYS и MSDOS.SYS (именно в этом порядке). Затем считываются и загружаются резидентные драйверы. Начинается формирование связанного списка драйверов устройств. Анализируется содержимое файла CONFIG.SYS, загружаются описанные в этом файле драйверы. Сначала загружаются драйверы, описанные параметром DEVICE, затем (только в MS-DOS версии 4.х и 5.0) резидентные программы, указанные операторами INSTALL. После этого считывается командный процессор и ему передается управление.
Командный процессор состоит из трех частей - резидентной, инициализирующей и транзитной. Первой загружается резидентная часть. Она обрабатывает прерывания INT 22H, INT 23H, INT 24H, управляет загрузкой транзитной части. Эта часть командного процессора обрабатывает ошибки MS-DOS и выдает запрос пользователю о действиях при обнаружении ошибок.
Инициализирующая часть используется только в процессе загрузки операционной системы. Она определяет начальный адрес, по которому будет загружаться пользовательская программа и инициализирует выполнение файла AUTOEXEC.BAT.
Транзитная часть командного процессора располагается в старших адресах памяти. В этой части находятся обработчики внутренних команд MS-DOS и интерпретатор командных файлов с расширением имени .BAT. Транзитная часть выдает системное приглашение (например, А:\> ), ожидает ввода команды оператора с клавиатуры или из пакетного файла и организует их выполнение.
После загрузки командного процессора и выполнения начальных процедур, перечисленных в файле AUTOEXEC.BAT, подготовка системы к работе завершается.
Для того чтобы правильно работать с системным программным и аппаратным обеспечением, нужно четко представлять себе механизм взаимодействия прикладной программы с компьютером. На рис. 1.1 показаны функциональные связи программы с программно-аппаратным обеспечением IBM PC.
Как правило, ядро DOS разделяют на несколько подсистем, каждая из которых отвечает за выполнение той или иной задачи. Как показано на рисунке, обычно выделяются следующие подсистемы:
Эти подсистемы общаются с аппаратурой через BIOS, драйверы или напрямую. Прикладное программное обеспечение может вызывать подсистемы DOS, работать с BIOS или непосредственно с аппаратурой. Обратите, однако, внимание на то, что прикладные программы могут обращаться к драйверам только через соответствующую подсистему DOS.
Очевидно также, что чем выше уровень интерфейса прикладной программы и аппаратуры, тем меньше программа будет зависеть от особенностей аппаратуры.
Рассмотрим подсистемы DOS отдельно.
Файловая система является одной из важнейших подсистем DOS. Она используется как в процессе загрузки операционной системы, так и в процессе ее работы. Сама операционная система записана на системном диске в виде файлов (IO.SYS, MSDOS.SYS, COMMAND.COM, драйверы, внешние команды и т.д.). Все прикладные программы и вообще все программы и данные для них хранятся на дисках в виде файлов, поэтому можно сказать, что файловая система - ключевая подсистема DOS.
Для обращения к файловой системе прикладная программа должна использовать специально предназначенные для этого функции прерывания DOS. Эти функции выполняют все файловые операции - создание, удаление файлов и каталогов, буферизованная и не буферизованная запись или чтение, получение справочной информации о состоянии файловой системы и другие. Файловые операции будут кратко описаны в обзоре прерываний DOS, кроме того, файловой системе полностью посвящена третья книга первого тома.
Файловая система работает с дисками через драйверы. Драйверы, в свою очередь, пользуются сервисом BIOS.
На уровне BIOS выполняются элементарные операции с диском, такие как чтение/запись секторов, форматирование и т.п. Этот низкий уровень доступен и прикладной программе, но обычно она пользуется функциями прерывания DOS, выполняющими все необходимые действия по обслуживанию каталогов и таблицы размещения файлов (File Allocation Table - FAT). Программы защиты от несанкционированного доступа или копирования вынуждены обращаться к средствам более низкого уровня, вызывая прерывания BIOS, или даже работать с контроллером дисковода через порты ввода/вывода.
Используя подсистему DOS, отвечающую за связь с драйверами, прикладные программы могут также выполнять элементарные операции с диском, такие как форматирование.
Эта подсистема DOS используется для распределения памяти запускаемым программам.
DOS управляет памятью с помощью блоков MCB (Memory Control Block). Память разбивается на блоки; каждому блоку предшествует MCB, в котором записаны характеристики блока памяти. Для каждой вновь запускаемой программы DOS создает определенное количество блоков MCB. При освобождении памяти или при выполнении запросов на получение дополнительной памяти DOS также использует блоки MCB, проверяя при этом правильность их содержимого.
Все блоки MCB располагаются друг за другом. Адрес первого блока хранится в векторной таблице связи, CVT, о которой мы будем говорить в главе 2. Там же будет описан формат блока управления памятью.
Прикладная программа может заказать для себя дополнительные блоки памяти. Для этого она обращается к системе управления памятью, используя функции прерывания 21h DOS.
При запуске программы DOS выполняет несколько операций. Сначала она обращается к системе управления памятью, чтобы подготовить блоки памяти для запускаемой программы. С помощью файловой системы файл, содержащий программу, загружается в память, после чего программа (это относится только к файлам типа .exe) настраивается на конкретный физический адрес. Только после этого программе передается управление.
Как известно, в MS-DOS существуют два формата выполняемых программ - .com и .exe. Способы запуска этих программ сильно различаются. Система управления программами автоматически распознает их и загружает в память по-разному. Мы еще вернемся к описанию различий между этими типами программ.
Другая задача, решаемая ситемой управления программами - запуск программ из программ и загрузка "программных перекрытий" - оверлеев. Если не все модули большого программного комплекса нужны одновременно, вы можете разбить комплекс на несколько частей. Это могут быть либо несколько отдельных программ, либо несколько оверлейных модулей. Каждый из этих способов имеет свои преимущества и недостатки; оба они пригодны для экономии памяти.
И наконец, последняя функция системы управления программами - работа с резидентными программами. Если вам надо, чтобы после завершения своей работы программа осталась резидентной в памяти, вы, как и в случае завершения обычной программы, обращаетесь к системе управления программами через соответствующую функцию прерывания DOS 21h.
Эта система скрыта от прикладных программ - программы не могут обращаться непосредственно к драйверам устройств ввода/вывода. Программа вызывает DOS, а DOS обращается при необходимости к драйверам.
Возможно, что запрет на непосредственный вызов драйверов введен для обеспечения совместимости с будущими версиями операционной системы, в которых механизм вызова драйверов может измениться. Однако, используя сведения, приведенные в этой книге, вы сможете обойти этот запрет и обратиться непосредственно к драйверу. При этом вам придется использовать некоторые недокументированные прерывания DOS, что само по себе нежелательно из-за возможной потери совместимости с другими версиями операционной системы.
Для управления состоянием устройства ввода/вывода или состоянием драйвера используется специальная функция 44h прерывания DOS 21h. Эта функция предназначена для обмена управляющей информацией между прикладной программой и драйвером.
Система обработки ошибок DOS проста и удобна. Для кодирования ошибок как правило используется флаг переноса (CARRY, CF). Если после обращения к прерыванию DOS флаг переноса установлен в 1, произошла ошибка. Для того чтобы проанализировать ошибку и предпринять какие-то действия, можно вызвать соответствующую функцию DOS, которая вернет уточняющую информацию об ошибке и предоставит соответствующие рекомендации (разумеется, лишь в виде кодов, находящихся в регистрах процессора).
Если произошла критическая ошибка ввода/вывода (например, прочитать дискету невозможно), вызывается стандартная процедура DOS, выводящая на экран запрос о дальнейших действиях. Пользовательская программа может подключить вместо системной свою программу обработки критических ошибок. Подробнее об обработке ошибок будет сказано в разделе 1.6.
Компьютер обычно оборудуется системными часами. Это могут быть КМОП-часы с питанием от аккумулятора, содержимое которых не сбрасывается при выключении питания компьютера, или таймер, регулярно вырабатывающий прерывания. В любом случае операционная система ведет подсчет времени и хранит текущие показания часов и дату.
Программа может опросить часы, обратившись к DOS с запросом через одну из функций прерывания 21h, или установить новое состояние часов.
Операционная система содержит драйвер устройства CLOCK$. Прикладная программа может обратиться к этому устройству для чтения показания часов или для установки часов. В книге 2 первого тома приведен пример программы для работы с устройством CLOCK$.
Программа может также использовать прерывания таймера для регулярного выполнения каких-либо функций.
Консоль оператора состоит из двух устройств - клавиатуры и дисплея. Эти два устройства обслуживаются одним драйвером - драйвером консоли CON. Т.е. можно считать, что в компьютере имеется устройство - консоль - с именем CON.
Операционная система обслуживает консоль с помощью функций прерывания 21h, обеспечивающих ввод и вывод символов на устройство CON. Для работы с физической клавиатурой и дисплейным адаптером этот драйвер использует прерывания BIOS.
DOS имеет набор драйверов для работы с печатающими устройствами и последовательными портами, которые обеспечивают прием/передачу символов и управление режимами работы устройств.
Кроме того, для печати текста в фоновом режиме в состав дистрибуции DOS входит программа PRINT.COM. Эта практически единственная "мультизадачная" утилита операционной системы является примером стандартной резидентной программы. Она позволяет выполнять параллельно с печатью текста другую работу (например, редактирование другого текста).
Специально следует отметить драйверы электронного диска и кэш-памяти. Драйвер электронного диска называется RAMDRIVE.SYS. Этот драйвер организует в расширенной или в дополнительной памяти компьютера быстрый псевдо-диск. Можно организовать электронный диск и в основной памяти, но основной памяти всегда мало!
Операционная система MS-DOS версий 4.01 и 5.0 имеет в своем составе систему управления дополнительной и расширенной памятью, которая реализуется драйвером HIMEM.SYS. Этот драйвер позволяет программам, составленным специальным образом, использовать расширенную или дополнительную память для хранения данных (но не для выполнения программ).
Если подключен драйвер HIMEM.SYS, то с помощью драйвера SMARTDRV.SYS можно создать кэш-память для жесткого диска. Особенно эффективно применение кэш-памяти для работы с базами данных, когда вам периодически требуется одна и та же информация. В следующий раз, когда информация потребуется, она будет доступна без обращения к диску.
Такое широко распространенное и ставшее стандартным для любого персонального компьютера устройство как мышь не поддерживается операционной системой. Для использования мыши следует подключить драйвер, который обычно поставляется вместе с этим устройством.
Другие устройства ввод/вывода (сканеры, плоттеры, стримеры и т.п.) также не поддерживаются DOS. Для этих устройств фирмы поставляют драйверы, которые надо подключить к операционной системе.
Как правило, любая программа работает с тем или иным устройством ввода/вывода. Программы для первых ЭВМ работали непосредственно с портами и регистрами этих устройств. Модули, выполняющие такие стандартные действия, как ввод данных с перфокарт или печать результатов вычислений, входили в состав пользовательских программ.
В начале своего развития микропроцессорные системы имели в своем составе программу, называемую "монитор". Эта программа обычно находилась в постоянном запоминающем устройстве и обслуживала устройства ввода/вывода: клавиатуру, дисплей, кассетный накопитель на магнитной ленте и др. Диалоговая часть монитора позволяла выполнять некоторые операторские функции: загрузку и запуск программы, отладку программы в пошаговом режиме, печать текстов, просмотр и редактирование содержимого памяти и т.п. Но самое главное - прикладные программы, составленные для этих систем, могли пользоваться модулями монитора для работы с периферийной аппаратурой и для выполнения других функций.
Программа уже не содержала все необходимые для ее работы модули, а пользовалась "стандартными" услугами программы-монитора. Такая организация программы не только уменьшила размер ее загрузочного модуля, но и позволила программистам сосредоточить свои усилия на решении основной задачи.
Как программа пользовалась услугами монитора? Механизм взаимодействия программы пользователя и монитора был реализован по-разному в разных системах. В худшем случае прикладная программа пользовалась известными абсолютными адресами модулей монитора, в лучшем - использовала специальные таблицы адресов программных модулей.
К сожалению, разные системы были несовместимы по составу модулей монитора и механизму их вызова, что сильно затрудняло, если не совершенно исключало их программную совместимость.
В первом массовом персональном компьютере IBM PC модули обслуживания стандартной периферии были записаны в постоянном запоминающем устройстве. Совокупность этих модулей (плюс программа начальной инициализации и тестирования) называется базовой системой ввода/вывода - Basic Input/Output System. Общепринятое сокращение - BIOS.
Выпускаемые различными фирмами компьютеры, совместимые с IBM PC, могут немного отличаться по типу периферийного оборудования, но для достижения совместимости с IBM PC модули BIOS нивелируют эти различия, предоставляя в распоряжение программы пользователя стандартный набор модулей для работы с устройствами ввода/вывода.
Не будет преувеличением сказать, что одна из причин такого невиданного успеха компьютера IBM PC на рынке персональных компьютеров - наличие хорошо продуманного стандартного интерфейса модулей BIOS и прикладных программ. Именно благодаря этому интерфейсу достигается почти стопроцентная совместимость по программному обеспечению компьютеров этого типа, выпускаемых разными фирмами.
В этом разделе книги мы расскажем о том, как прикладные программы, составленные для компьютера, совместимого с IBM PC, могут пользоваться модулями BIOS для работы со стандартной периферией, затем приведем краткий обзор основных модулей BIOS.
Напомним вам, что такое программные прерывания, так как именно они используются для вызова модулей BIOS.
В начале оперативной памяти персонального компьютера (в пределах первого килобайта) находится так называемая векторная таблица прерываний. Она состоит из 256 ячеек, хранящих адреса программ-обработчиков прерывания. Мы будем подробно изучать эту таблицу в главе 4, а сейчас вспомним машинную команду INT <n>.
По этой команде содержимое ячейки векторной таблицы прерываний с номером n помещается в адресные регистры процессора, причем в стеке запоминается текущее содержимое адресных регистров. Управление передается по адресу, записанному в ячейке таблицы. Программа-обработчик прерывания должна заканчиваться командой IRET, по которой из стека извлекается старое значение адресных регистров и управление передается обратно в программу, вызвавшую прерывание командой INT <n>.
Вообще говоря, процедура вызова и обработки программного прерывания похожа на процедуру вызова подпрограммы. Отличие заключается в том, что вызывающая программа "не знает" абсолютного адреса модуля обработки прерывания в памяти. Поэтому работа программ не зависит от адресов расположения модулей обработчиков прерывания.
Для вызова модуля BIOS программа использует команду INT <n> с соответствующим номером n. Программа передает параметры модулям BIOS через регистры процессора, результат работы модуля возвращается также в регистрах.
Не все номера прерываний n используются BIOS. Часть из них предназначена для аппаратных прерываний от устройств ввода/вывода, часть зарезервирована для DOS, часть - для программ пользователя.
Подробно прерывания BIOS будут изучаться во втором томе, так как описание этих прерываний трудно отделить от описания особенностей аппаратуры. Приводимый здесь обзор предназначен в основном для иллюстрации основных возможностей BIOS по обслуживанию периферии, поэтому в обзор вошли не все прерывания BIOS, а только самые важные. Остальные прерывания будут изучаться по мере необходимости при изложении соответствующего материала.
Прежде чем пытаться работать с каким-либо устройством ввода/вывода, следует убедиться в том, что оно есть в составе оборудования компьютера. В процессе инициализации тестовые модули, находящиеся в BIOS, динамически определяют состав аппаратного обеспечения машины и записывают конфигурацию системы в специально отведенную для этого ячейку памяти.
Программа, вызывая прерывание INT 11h, получает в регистре AX содержимое этой ячейки. Каждый бит в слове конфигурации отвечает за соответствующее устройство.
Анализируя слово конфигурации, программа может узнать, входят ли в состав оборудования компьютера дискеты и если входят, то сколько дисководов имеется в наличии, присутствует ли арифметический сопроцессор, какой начальный режим дисплейного адаптера используется, сколько в системе принтеров, адаптеров последовательного интерфейса RS232, подключен ли игровой адаптер (джойстик)?
Обычно прикладная программа не работает сама с аппаратурой, а пользуется услугами операционной системы. При обращении к стандартной аппаратуре через операционную систему программа пользователя получит признак ошибки, если запрашиваемое устройство отсутствует. Программы, составленные на языке программирования Си при использовании библиотеки эмуляции арифметического сопроцессора, сами определяют, имеется сопроцессор или нет, и не пытаются пользоваться отсутствующим устройством. Операции сопроцессора эмулируются центральным процессором и программа просто работает медленнее.
Но если программа обращается непосредственно к портам ввода/вывода отсутствующего устройства, это может привести в лучшем случае к зависанию системы.
Сказанное выше справедливо и по отношению к оперативной памяти. Для работы некоторых программ требуется достаточное количество памяти. Прерывание INT 12h возвращает в регистре AX количество имеющихся блоков памяти размером в один килобайт. Анализируя эту величину, программы могут при нехватке памяти либо вывести на экран соответствующее сообщение и отказаться от работы, либо изменить алгоритмы работы, организовав, например, "виртуальную" память на диске или просто записывая в файл промежуточные результаты.
Если Ваш компьютер оборудован расширенной памятью (адресное пространство этой памяти находится выше границы в 1 мегабайт), размер этой памяти в килобайтах можно узнать, вызвав прерывание INT 15h со значением регистра AX, равным 8800h.
Прерывание INT 10h выполняет все многочисленные операции по обслуживанию дисплейного адаптера.
При вызове прерывания INT 10h, как и при вызове многих других прерываний, регистр AH содержит номер функции, которую требуется выполнить. Остальные регистры при вызове прерывания содержат операнды.
Программирование дисплейного адаптера - сложная задача. Функции, выполняемые прерыванием INT 10h обширны, полностью они будут описаны во втором томе книги. Приведем краткий обзор функций прерывания INT 10h.
Эта функция обычно вызывается первой при начале работы с дисплейным адаптером или при необходимости изменить текущий режим адаптера. Что здесь имеется в виду?
Напомним, что дисплейный адаптер может работать либо в текстовом, либо в графическом режиме. На самом деле существует несколько текстовых и несколько графических режимов, различающихся количеством строк и столбцов, способом представления цвета и т.д.
В процессе инициализации BIOS задает начальный режим адаптера исходя из его типа. Если Вашей программе нужен другой режим, отличный от исходного, она должна использовать эту функцию. При этом необходимо учитывать, что дисплейные адаптеры могут поддерживать не все режимы.
С помощью этой функции вы можете установить размер и форму курсора, сделать курсор мигающим или убрать его совсем.
Эта функция позволяет управлять расположением курсора на экране, в частности, один из способов убрать курсор - расположить его за пределами экрана, например, на несуществующей 26 строке.
Программа может узнать в любое время, где расположен курсор. Это может потребоваться ей, например, для того, чтобы переместить курсор в следующую позицию (вправо, вверх, вниз, на 10 символов левее текущего положения и т.д.).
Световое перо используется относительно редко, однако если оно есть, то функция 04h позволит вам работать с этим устройством.
Компьютер хранит, как правило, не один отображаемый образ экрана, а несколько. Для этого видеопамять (память для хранения видеоизображения, находится на плате видеоконтроллера) разбивается на так называемые страницы. Отображается только активная страница видеопамяти.
Используя механизм страниц, программа может заранее подготовить изображение в неактивной странице, затем сделать подготовленную страницу активной. Изображение новой страницы мгновенно появится на экране.
Некоторые отладчики программ используют одну страницу видеопамяти для отлаживаемой программы, другую - для выдачи своих диагностических сообщений.
С помощью этих функций вы сможете переместить выбранную область окна на заданное число строк вверх или вниз. Освободившееся место будет заполняться пустыми строками. Одно из применений этой функции - полная очистка экрана.
С помощью этих функций можно прочитать или записать символ и его атрибут. При записи символа можно задать число повторений. Функцию записи с повторением удобно использовать для заполнения области экрана каким-либо символом.
Запись/чтение символа начинается с текущего положения курсора.
Эта функция предназначена для записи символа в видеопамять без задания для него индивидуального значения атрибута. Используется текущий атрибут. Можно задавать кратность записи.
Эта функция позволяет управлять цветом рамки вокруг изображения в текстовом режиме и цветом фона в графическом режиме (для адаптеров EGA, VGA).
При составлении программ обработки ошибок следует учитывать, что для DOS версии 1.0 при некоторых ошибках функции DOS возвращают в регистре AX значение 0FFh. Начиная с версии DOS 2.0, при ошибке устанавливается флаг переноса, код ошибки записывается в регистр AX. Однако для более полной диагностики причины ошибки следует использовать функцию 59h прерывания INT 21h.
Если Ваша программа, составленная на языке Си, вызывает функции DOS неявным образом (через функции стандартной библиотеки транслятора, такие как fprintf, puts и т.д.), то можно воспользоваться средствами обработки ошибок, входящими в состав стандартной библиотеки.
Когда при обращении к функциям DOS средствами стандартной библиотеки транслятора Си возникает ошибка, то в глобальную переменную errno записывается код ошибки.
Возможны следующие коды ошибок (они описаны в файле errno.h и stdlib.h):
ECHILD | Нет порожденных процессов. Задача, не имеющая подзадач, выдала команду ожидания, или была выдана команда ожидания для подзадачи, имеющей признак NO-WAIT. |
EAGAIN | Больше нет процессов. Попытка создать новый процесс окончилась неудачно, т.к. либо больше нет резервов для создания процессов, либо недостаточно оперативной памяти, либо превышен максимальный уровень вложенности процессов. |
E2BIG | Слишком велик список аргументов. Либо размер списка аргументов превышает 128 байт, либо требуемый размер памяти для среды превышает 32К. |
EACCES | Доступ запрещен. Затребованный вид доступа к файлу запрещен или несовместим с установленными атрибутами файла (или каталога). Этот код ошибки передается при попытке чтения из неоткрытого файла, при попытке записи в файл, защищенный от записи, или при попытке открыть каталог как файл. |
EBADF | Плохой номер файла. Номер файла, использованный при вызове функции, имеет неверное значение или не относится к открытому файлу, или сделана попытка записи в открытый только для чтения файл или устройство. |
EDEADLOCK | Произошла блокировка ресурсов. Произведено 10 неудачных попыток заблокировать файл. Этот код ошибки используется только DOS версии 3.0 и более поздних версий. |
EDOM | Ошибка в аргументе математической функции. Аргумент математической функции вышел за пределы области определения этой функции. |
EEXIST | Файл уже существует. Сделана попытка создать файл с именем, которое уже используется существующим файлом. |
EINVAL | Неверный аргумент. Для одного из аргументов функции было задано неверное значение. |
EMFILE | Открыто слишком много файлов. Исчерпан запас номеров файлов , нельзя больше открыть ни одного файла. |
ENOENT | Нет такого файла или каталога. Запрошенный файл или каталог отсутствует или не может быть найден. |
ENOEXEC | Сделана попытка выполнить загрузочный файл, имеющий неправильный формат. |
ENOMEM | Недостаточно памяти. Эта ошибка появляется, когда недостаточно памяти для запуска процесса или для удовлетворения запроса программы на выделение блока памяти. |
ENOSPC | Нет свободного места на устройстве. На устройстве нет места для записи информации (например, переполнился диск). |
ERANGE | Слишком большой результат. Слишком большой по величине аргумент математической функции привел к частичной или полной потере значимости результата. |
EXDEV | Связь различных устройств. Сделана попытка переслать файл на другое устройство, используя функцию переименования. |
Из приведенного выше списка кодов ошибок видно, что средствами стандартной библиотеки транслятора обрабатываются не только ошибки, возникающие при обращении к функциям DOS, но и ошибки, появляющиеся при работе с математическим функциями.
Для диагностической выдачи сообщения об ошибке можно использовать функции perror и strerror. Первая функция выводит в stderr соответствующее сообщение об ошибке, вторая только формирует строку сообщения. Функции perror и strerror имеют операнд - указатель на строку. Эта строка добавляется в начало стандартного сообщения об ошибке. Если к стандартному сообщению ничего добавлять не надо, операнд должен иметь значение NULL.
Следует заметить, что значение переменной errno отражает последнюю ошибку. Успешный вызов функции не приводит к автоматическому сбросу переменной errno.
Поэтому функции perror и strerror необходимо вызывать сразу после того, как вызываемая функция возвратит признак ошибки.
Приведем пример программы, обрабатывающей ошибки с использованием переменной errno:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> void main(int argc, char *argv[]) { FILE *stream; // Открываем файл только для чтения stream = fopen(argv[1], "r"); // Если произошла ошибка, выводим сообщение if( (stream == NULL) || (ferror(stream)) ) { perror("Не могу открыть файл"); exit(errno); } // Пытаемся произвести запись в файл, который // открыт только для чтения. Это приведет к ошибке. fprintf(stream, "Пишем в файл\n"); if( (stream == NULL) || (ferror(stream)) ) { // Выводим сообщение об ошибке двумя способами - // с помощью функции perror и strerror perror("Запись в защищенный файл"); printf("Запись в защищенный файл: %s\n", strerror(errno)); exit(errno); } exit( 0 ); }
DOS имеет еще одно средство для обработки ошибок - обработчик критических ошибок (Critical Error Handler). Этот модуль вызывается DOS, когда она получает сообщение об ошибке от драйвера устройства.
Модуль выдает на экран хорошо известное вам сообщение:
Abort, Retry, Ignore?
Это сообщение обычно появляется тогда, когда вы забываете вставить дискету или начинаете печатать при отключенном принтере.
Прикладные программы могут подключать свой модуль обработки критических ошибок вместо стандартного. Мы научимся обрабатывать критические ошибки в книге 3. Там же будет приведен соответствующий пример.