Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MS DOS для профи.doc
Скачиваний:
10
Добавлен:
22.09.2019
Размер:
381.95 Кб
Скачать

1.7. Вызов прерываний ms-dos

Программы, составленные на языке С, обращаются к прерываниям MS-DOS обычно с помощью таких функций, как intdos, int86, intdosx и т. д.

Для передачи параметров используются структуры REGS, WORDREGS, BYTEREGS, SREGS, описанных в файле dos.h. Программа записывает параметры в поля структуры, соответствующие регистрам процессора, а затем вызывает одну из перечисленных выше функций, передавая ей адрес структуры. После выполнения прерывания результат записывается в эту же или другую структуру. Например:

union REGS inregs, outregs;

struct SREGS segregs;

....

inregs.h.ah = 0x3a;

segregs.ds = FP_SEG(dir_name);

inregs.x.dx = FP_OFF(dir_name);

intdosx(&inregs, &outregs, &segregs);

....

В этом фрагменте кода вызывается функция 3Ah прерывания INT 21h, для чего используется функция intdosx, которая входит в стандартную библиотеку системы разработки Borland C++.

Номер функции записывается в поле h.ah объединения inregs, параметры функции (передаваемые через регистры DS:DX), соответственно, в поле ds структуры segregs и в поле x.dx объединения inregs.

Функция intdosx записывает содержимое регистров процессора после выполнения программного прерывания в объединение outregs.

Объединение REGS определено в файле dos.h следующим образом:

union REGS{

struct WORDREGS x;

struct BYTEREGS h;

};

В нем имеется две структуры - WORDREGS и BYTEREGS.

Первая из этих структур предназначена для работы с 16-разрядными регистрами. Она определена так:

struct WORDREGS{

unsigned int ax, bx, cx, dx, si, di, cflag, flags;

};

В этой структуре поля ax, bx, cx, dx, si и di соответствуют одноименным регистрам процессора.

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

С помощью структуры BYTEREGS вы можете задавать (и определять) содержимое 8-разрядных регистров процессора:

struct BYTEREGS

{

unsigned char al, ah, bl, bh, cl, ch, dl, dh;

};

И, наконец, для работы с сегментными регистрами предназначена структура SREGS, определенная следующим образом:

struct SREGS{

unsigned int es;

unsigned int cs;

unsigned int ss;

unsigned int ds;

};

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

include <dos.h>

После вызова программного прерывания программа должна проверить флаг переноса, который сохраняется в поле cflag. Проверка поля cflag может быть выполнена, например, таким образом:

union REGS inregs, outregs;

....

intdos(&inregs, &outregs);

if(outregs.x.cflaf != 0) error();

....

Код ошибки при этом записывается в переменную outregs.x.ax.

1.8. Программа errcode

Приведем пример программы с именем ERRCODE (листинг 1.1), которая стирает каталог с именем DIR в текущем каталоге и, в случае ошибки, выводит расширенную информацию об ошибке, класс ошибки, код предполагаемых действий и код локализации ошибки.

Листинг 1.1. Файл errcode\errcode.cpp

#include <dos.h>

#include <stdio.h>

#include <conio.h>

union REGS inregs, outregs;

struct SREGS segregs;

void main(void);

void main(void)

{

char far *dir_name = "DIR";

// Стираем каталог с именем DIR. Для этого вызываем

// функцию 0x3A прерывания INT 21h

inregs.h.ah = 0x3a;

segregs.ds = FP_SEG(dir_name);

inregs.x.dx = FP_OFF(dir_name);

intdosx(&inregs, &outregs, &segregs);

// Если после выполнения прерывания установлен

// флаг переноса, выводим сообщение об ошибке

if(outregs.x.cflag != 0)

{

printf("\n\nОшибка при удалении каталога:\t%d",

outregs.x.ax);

// Получаем расширенную информацию об ошибке

// с помощью функции 0x59 прерывания INT 21h

inregs.h.ah = 0x59;

inregs.x.bx = 0;

// Сохраняем регистры в стеке, так как их содержимое

// изменится

asm push ds

asm push es

asm push si

asm push di

// Вызываем прерывание

intdosx(&inregs, &outregs, &segregs);

// Восстанавливаем содержимое регистров

asm pop di

asm pop si

asm pop es

asm pop ds

// Выводим расширенную информацию об ошибке

printf("\nРасширенный код ошибки: \t%d"

"\nКласс ошибки: \t%d"

"\nПредполагаемые действия:\t%d"

"\nЛокализация ошибки: \t%d",

outregs.x.ax, outregs.h.bh,

outregs.h.bl, outregs.h.ch);

}

printf("\n\nНажмите любую клавишу...");

getch();

}

При составлении программ обработки ошибок следует учитывать, что некоторые старые функции MS-DOS возвращают при ошибке в регистре AX значение 0FFh. Начиная с версии MS-DOS 2.0 в случае возникновения ошибки устанавливается флаг переноса. При этом код ошибки записывается в регистр AX. Однако для более полной диагностики причины ошибки следует использовать функцию 59h прерывания INT 21h.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]