- •Аннотация
 - •Введение
 - •Благодарности
 - •Авторский компакт-диск
 - •Как связаться с авторами
 - •1 Определение конфигурации компьютера
 - •Определение конфигурации с помощьюBios
 - •Наличие нмд
 - •Наличие арифметического сопроцессора
 - •Начальный режим работы видеоадаптера
 - •Стандартная оперативная память
 - •Расширенная оперативная память
 - •ПрограммаHdwcfg
 - •Код модели компьютера и версияBios
 - •ПрограммаBiosinfo
 - •Конфигурация в памяти cmos
 - •00H - 0Dh - область часов реального времени
 - •0Eh - байт диагностики
 - •0Fh - байт отключения
 - •10H - тип накопителей нгмд
 - •11H - зарезервировано дляIbm pc/at, тип нмд дляIbm ps/2
 - •12H - тип первого и второго нмд
 - •13H - зарезервировано
 - •14H - конфигурация оборудования
 - •15H-16h - объем стандартной оперативной памяти
 - •ПрограммаCmosshow
 - •Определение типа центрального процессора
 - •МоделиIntel 8086/8088
 - •Модель Intel 80286
 - •МодельIntel 80386
 - •МодельIntel 80486
 - •Команда cpuid
 - •ПрограммаCpuinfo
 - •2 Клавиатура
 - •Как работает клавиатура
 - •Клавиатурная матрица
 - •Скан-код клавиши
 - •КодAscii нажатой клавиши
 - •Режим автоповтора
 - •Типы клавиатур
 - •Порты для работы с клавиатурой
 - •КомпьютерIbm pc/xt
 - •Современные компьютеры
 - •ПрограммаKbdled
 - •Аппаратное прерывание клавиатуры
 - •Стандартный обработчик прерывания int 09h
 - •Буфер клавиатуры
 - •Переключающие клавиши
 - •Средства bios для работы с клавиатурой
 - •Чтение символа с ожиданием
 - •ПрограммаKbdscan
 - •Проверка буфера на наличие в нем символов
 - •ПрограммаChkbuf
 - •Получение состояния переключающих клавиш
 - •Установка временных характеристик клавиатуры
 - •Запись символов в буфер клавиатуры
 - •Чтение символа с ожиданием для 101-клавишной клавиатуры
 - •Проверка буфера на наличие в нем символов для 101-клавишной клавиатуры
 - •Получение состояния переключающих клавиш для 101-клавишной клавиатуры
 - •Режимы работы клавиатуры
 - •Сравнение режимов
 - •Изменение режима
 - •Средства ms-dos для работы с клавиатурой
 - •Буферизованный ввод с эхо-выводом
 - •Буферизованный ввод без эхо-вывода
 - •Нефильтрованный ввод без эхо-вывода
 - •Вводс консоли и вывод на консоль
 - •Ввод строки символов
 - •Проверка состояния стандартного ввода
 - •Сброс буфера клавиатуры
 - •Клавиатурные функции стандартной библиотеки c
 - •Функции getch и getche
 - •ПрограммаKbdascii
 - •Функцияkbhit
 - •ПрограммаKbdhit
 - •Функция cgets
 - •Функция gets
 - •Функция scanf
 - •Как устроена мышь?
 - •Драйверы мыши в ms-dos
 - •Прерывание для обслуживания мыши
 - •Инициализация мыши
 - •Включить курсор мыши
 - •Выключить курсор мыши
 - •ПрограммаMscursor
 - •Определить положение курсора
 - •ПрограммаMsgcurs
 - •Установить курсор
 - •Определить положение курсора при нажатии клавиши
 - •Определить положение курсора при отпускании клавиши
 - •Задать диапазон движения курсора по горизонтали
 - •Задать диапазон движения курсора по вертикали
 - •Задать форму курсора в графическом режиме
 - •ПрограммаMsgform
 - •Задать форму курсора в текстовом режиме
 - •ПрограммаMstform
 - •Определить содержимое счетчиков перемещения
 - •Установить драйвер событий
 - •ПрограммаMsdriver
 - •Включить эмуляцию светового пера
 - •Выключить эмуляцию светового пера
 - •Задать скорость перемещения курсора мыши
 - •Установить область исключения для курсора
 - •Задать увеличенный графический курсор
 - •Определить порог удвоения скорости
 - •Заменить драйвер событий
 - •Определить размер буфера состояния драйвера
 - •Сохранить состояние драйвера
 - •Восстановить состояние драйвера
 - •Установить альтернативный драйвер событий
 - •Получить адрес альтернативного драйвера событий
 - •Установить чувствительность мыши
 - •Определить чувствительность мыши
 - •Установить частоту прерываний для Inport Mouse
 - •Установить номер страницы видеопамяти
 - •Определить номер страницы видеопамяти
 - •Отключить драйвер мыши
 - •Восстановить драйвер мыши
 - •Сбросить драйвер мыши
 - •Определить тип мыши
 - •МышьMicrosoft IntelliMouse
 - •Проверка наличия мыши Microsoft IntelliMouse
 - •Проверка в среде Microsoft Windows 95 и Microsoft Windows nt версии 3.51
 - •Проверка в среде Microsoft Windows nt версии 4.0
 - •Определение величины свертки
 - •Определение величины свертки в среде Microsoft Windows 95 и Microsoft Windows nt версии 3.51
 - •Определение величины свертки в среде Microsoft Windows nt версии 4.0
 - •Сообщение msh_mousewheel
 - •Сообщение wm_mousewheel
 - •Другие сообщения от мыши Microsoft IntelliMouse
 - •ПриложениеRtfpad
 - •4 Часы реального времени
 - •Регистры часов реального времени
 - •Регистры счетчиков
 - •Регистр состоянияA
 - •Регистр состояния b
 - •Регистр состояния c
 - •Регистр состояния d
 - •Прерывание от часов реального времени
 - •Функции прерыванияInt 1Ah
 - •Сброс будильника
 - •ПрограммаRtcalarm
 - •5 Системный таймер
 - •Обработка прерываний таймера
 - •Микросхемы таймера 8253 и 8254
 - •Режимы работы таймера
 - •Режим однократного выполнения функций
 - •Работа с перезапуском
 - •Формат управляющего регистра
 - •Формат команды чтения слова состояния канала
 - •Формат слова состояния канала
 - •Последовательность действий
 - •ПрограммаTimerst
 - •Средства bios для работы с таймером
 - •Чтение счетчика таймера
 - •Установка счетчика таймера
 - •Установка таймера с сигнализацией
 - •Формирование задержки
 - •Второй способ проигрывания музыки
 - •Проигрывание музыки в фоновом режиме
 - •ПрограммаTmsound
 - •ПрограммаIosound
 - •ПрограммаRandom
 - •6 Асинхронный последовательный адаптер
 - •Основные понятия и термины
 - •Аппаратная реализация
 - •МикросхемаUart
 - •Разъемы адаптера
 - •Порты асинхронного адаптера
 - •Порт 3f8h
 - •Порт 3f9h
 - •Порт 3fAh
 - •Порт 3fBh
 - •Порт 3fCh
 - •Порт 3fDh
 - •Порт 3fEh
 - •Функции bios для работы с последовательным асинхронным адаптером
 - •Инииализация портов асинхронного адаптера
 - •Передача байта
 - •Прием байта
 - •Определение состояния асинхронного адаптера
 - •Программирование асинхронного адаптера
 - •Инициализация асинхронного адаптера
 - •Передача данных
 - •Прием данных
 - •ПрограммаComtest
 - •Использование прерываний
 - •7 Параллельный адаптер
 - •Порты параллельного адаптера
 - •Порт 378h
 - •Порт 37Ah
 - •Порт 379h
 - •Разъем параллельного адаптера
 - •Вывод байта на принтер через параллельный адаптер
 - •Функции bios для работы с принтером
 - •Печать символа
 - •Инициализация принтера
 - •Определение состояния принтера
 - •ПрограммаPrintfl
 - •Функции ms-dos для работы с принтером
 - •ФункцияMs-dos для вывода на принтер
 - •Система буферизованной печати
 - •Проверка установки системы буферизованной печати
 - •Запуск процесса печати файла
 - •Отмена печати файла
 - •Отмена печати всех файлов
 - •Определение состояния и блокировка системы буферизованной печати
 - •Разблокирование системы буферизованной печати
 - •Коды ошибок
 - •Программирование принтера
 - •Подключение принтера к компьютеру
 - •Установка переключателей конфигурации
 - •Программирование режимов работы принтера
 - •Инициализация принтера
 - •Контроллер прямого доступа ibm pc/xt
 - •Регистры каналов dma
 - •Порты 00h - 07h
 - •Порт 08h
 - •Порт 09h
 - •Порт 0Ah
 - •Порт 0Bh
 - •Порт 0Ch
 - •Порт 0Dh
 - •Порт 0Eh
 - •Порт 0Fh
 - •Порты 81h-8Fh
 - •Инициализация канала dma
 - •Контроллер прямого доступа ibm at
 - •Регистры каналовDma
 - •Регистры страниц
 - •Порты 0c0h - 0dFh
 - •Порты 0d0h-0dFh
 - •9 Устройство чтения cd-rom
 - •Драйвер устройства чтенияCd-rom
 - •РасширениеMscdex
 - •ФункцииMscdex
 - •Определение количества устройствCd-rom
 - •Получение списка устройств cd-rom
 - •Получение имени файла прав собственности
 - •Получение имени файла резюме
 - •Получение имени файла библиографической документации
 - •Чтение сектора оглавления компакт-диска
 - •Чтение сектора по абсолютному адресу
 - •Проверка устройства чтения cd-rom
 - •Определение версии mscdex
 - •Определение обозначения устройств чтения cd-rom
 - •Вызов драйвера cd-rom
 - •Работа через драйверCd-rom
 - •Заголовок запроса
 - •Команды драйвера cd-rom
 - •Инициализация
 - •ЧтениеIoctl Input
 - •Определение адреса заголовка драйвера cd-rom
 - •Определение положения головки
 - •Получение информации о звуковых каналах
 - •Чтение данных из устройства
 - •Определение состояния устройства
 - •Определение размера сектора
 - •Определение размера тома
 - •Проверка замены носителя данных
 - •Получение информации о компакт-диске
 - •Получение информации о дорожкекомпакт-диска
 - •Получение информации о канале q
 - •Получение информации о подканале
 - •Получение штрих-кода изготовителя компакт-диска
 - •Сброс входных буферов
 - •ЗаписьIoctl Output
 - •Извлечение компакт-диска
 - •Блокирование и разблокирование компакт-диска в устройстве
 - •Сброс устройства чтения cd-rom
 - •Управление звуковыми каналами
 - •Запись в устройство управляющей строки
 - •Чтение длинное с предварительной выборкой
 - •Проигрывание звуковой дорожки
 - •Остановка проигрывания звуковой дорожки
 - •Возобновление проигрывания звуковой дорожки
 - •ПрограммаCdinfo
 - •ПрограммаCdplay
 - •10 Арифметический сопроцессор
 - •Вещественные числа
 - •Целые числа
 - •Регистры сопроцессора
 - •Численные регистры
 - •Регистр тегов
 - •Регистр управления
 - •Регистр состояния
 - •Регистры указателя команды и указателя операнда
 - •Система команд сопроцессора
 - •Команды пересылки данных
 - •Запись в стек
 - •Извлечение из стека
 - •Копирование данных
 - •Загрузка констант
 - •Арифметические команды
 - •Команды сравнений чисел
 - •Трансцендентные команды
 - •Управляющие команды
 - •Программирование сопроцессора
 - •ПрограммаNpu1
 - •Обработка особых случаев
 - •Неточный результат
 - •Переполнение
 - •Антипереполнение
 - •Деление на нуль
 - •Недействительная операция
 - •Денормализованный операнд
 - •Ошибка в процессореPentium
 - •11 Расширенная память
 - •Основные понятия
 - •Установка драйвера himem.Sys
 - •Спецификация xms
 - •Проверка подключения драйвера
 - •Получение адреса управляющей программы
 - •Описание функций драйвера himem.Sys
 - •Получить версию xms
 - •Запросить область hma
 - •Освободить область hma
 - •Глобальное открывание линии a20
 - •Глобальное закрывание линии a20
 - •Освободить блок emb
 - •Копирование блоков emb
 - •Блокирование emb
 - •Разблокирование emb
 - •Получить информацию об идентификаторе блока emb
 - •Изменить размер emb
 - •Запросить область umb
 - •Освободить область umb
 - •Коды ошибок
 - •Ограничения при использовании области hma
 - •Примеры программ
 - •ПрограммаTesthma
 - •ПрограммаCallhma
 - •Предметный указатель
 - •Литература
 - •Оглавление
 - •1 Определение конфигурации компьютера 7
 - •2 Клавиатура 38
 - •3 Мышь 64
 - •4 Часы реального времени 102
 - •5 Системный таймер 113
 - •6 Асинхронный последовательный адаптер 132
 - •7 Параллельный адаптер 149
 - •8 Контроллер прямого доступа к памяти 162
 - •9 Устройство чтения cd-rom 170
 - •10 Арифметический сопроцессор 216
 - •11 Расширенная память 243
 
ПрограммаCdplay
Программа CDPLAY предназначена для проигрывания дорожек звуковых компакт-дисков. При запуске этой программы необходимо указать параметр – номер блока, с которого должно выполняться проигрывание.
Ниже мы привели пример запуска программы, передав ей адрес 512:
CDPLAY, (c) A. Frolov, 1997
Track Red book: 512
Track Sierra: 0
MSCDEX version: 2.95
Found 1 CD Unit, start unit: G
CD-ROM letters: G
Started. Press any key to stop and eject CD
Этот адрес мы взяли из листинга, полученного программой CDINFO, описанной в предыдущем разделе. Он был пересчитан программойCDPLAY в форматSierra, в результате чего программа запустила проигрывание самой первой звуковой дорожки диска.
Если после запуска программы и начала проигрывания нажать любую клавишу, проигрывание будет остановлено, а компакт-диск - извлечен из устройства чтения CD-ROM.
Исходный текст программы CDPLAY приведен в листинге 9.2.
Листинг 9.2. Файлcdplay\cdplay.с
// =====================================================
// Проигрывание звуковых компакт-дисков
//
// (C) Фролов А.В, 1997
//
// E-mail: frolov@glas.apc.org
// WWW: http://www.glasnet.ru/~frolov
// или
// http://www.dials.ccas.ru/frolov
// =====================================================
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <dos.h>
#include <memory.h>
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;
// Необходимо для обеспечения выравнивания
// полей структур на границу байта
#pragma pack(1)
// Заголовок запроса для обращения к драйверу
typedef struct _ReqHdr
{
BYTE bSize;
BYTE bSubUnit;
BYTE bCmd;
WORD wStatus;
BYTE bReserved[8];
} ReqHdr;
typedef struct _PlayAudio
{
ReqHdr rh;
BYTE bMode;
DWORD dwLoc;
DWORD dwSectorNum;
} PlayAudio;
// Запрос IOCTL Output
typedef struct _IOCTL_Output
{
ReqHdr rh;
BYTE bMediaDescriptor;
DWORD lpTransferAddress;
WORD wDataSize;
WORD wStartSector;
DWORD lpVolID;
} IOCTL_Output;
// Запрос на извлечение компакт-диска
typedef struct _EjectDisk
{
BYTE bControl;
} EjectDisk;
#pragma pack()
// Прототипы функций
void GetCDLetters(BYTE *bLetters);
void CallCDDriver(void *rh, int nCDUnit);
int PlayAudioTrack(DWORD dwLoc, DWORD dwSectorNum, int nCDUnit);
int StopAudio(int nCDUnit);
int DeviceOpen(int nCDUnit);
int DeviceClose(int nCDUnit);
int EjectCD(int nCDUnit);
DWORD Red2Sierra(DWORD dwRedLoc);
// Регистры для вызова функции int86
union REGS rg;
// Количество установленных устройств чтения CD-ROM
int nCDUnits;
// Номер первого устройства чтения CD-ROM
int nCDStartUnit;
// Слово состояния после вызова драйвера CD-ROM
int iStatus;
// Массив номеров установленных устройств CD-ROM
BYTE bLetters[26];
// ---------------------------------------------------
// main
// Точка входа в программу
// ---------------------------------------------------
int main(int argc, char *argv[])
{
int i;
DWORD dwStartTrack;
printf("CDPLAY, (c) A. Frolov, 1997\n\n");
dwStartTrack = 1;
if(argc == 2)
{
dwStartTrack = atol(argv[1]);
printf("Track Red book: %ld\n", dwStartTrack);
}
else
{
printf("Usage: CDPLAY <Red book sector address>\n");
return -1;
}
// Преобразование адреса сектора в формат Sierra
dwStartTrack = Red2Sierra(dwStartTrack);
printf("Track Sierra: %ld\n", dwStartTrack);
// Проверяем, установлена ли программа MSCDEX
rg.x.ax = 0x1500;
rg.x.bx = 0;
int86(0x2f, &rg, &rg);
if(rg.x.bx == 0)
{
printf("MSCDEX is not installed\n");
return -1;
}
else
{
// Сохраняем общее количество устройств чтения CD-ROM
nCDUnits = rg.x.bx;
// Сохраняем номер первого такого устройства
nCDStartUnit = rg.x.cx;
// Определяем и отображаем вресию MSCDEX
rg.x.ax = 0x150c;
int86(0x2f, &rg, &rg);
printf("MSCDEX version: %d.%d\n", rg.h.bh, rg.h.bl);
// Отображаем количество найденных устройств чтения
// CD-ROM и номер первого устройства
printf("Found %d CD Unit, start unit: %c\n",
nCDUnits, nCDStartUnit + 'A');
}
// Получаем массив номеров устройств чтения CD-ROM
GetCDLetters(bLetters);
// Отображаем обозначения всех устройств CD-ROM
printf("CD-ROM letters: ");
for(i = 0; i < nCDUnits; i++)
{
printf("%c ", bLetters[i] + 'A');
}
printf("\n");
// Открываем устройство
iStatus = DeviceOpen(bLetters[0]);
if(iStatus & 0x8000)
{
printf("DeviceOpen status: %04.4X\n", iStatus);
return -1;
}
// Запускаем проигрывание
iStatus =
PlayAudioTrack(dwStartTrack, 0xffffffff, bLetters[0]);
if(iStatus & 0x8000)
{
printf("PlayAudioTrack status: %04.4X\n", iStatus);
return -1;
}
printf("Started. Press any key to stop and eject CD\n");
// Ожидаем, пока пользователь не нажмет клавишу
getch();
// Останавливаем проигрывание
iStatus = StopAudio(bLetters[0]);
if(iStatus & 0x8000)
{
printf("StopAudio status: %04.4X\n", iStatus);
return -1;
}
// Извлекаем диск
iStatus = EjectCD(bLetters[0]);
if(iStatus & 0x8000)
{
printf("EjectCD status: %04.4X\n", iStatus);
return -1;
}
// Закрываем устройство
iStatus = DeviceClose(bLetters[0]);
if(iStatus & 0x8000)
{
printf("DeviceClose status: %04.4X\n", iStatus);
return -1;
}
return 0;
}
// ---------------------------------------------------
// PlayAudioTrack
// Запуск проигрывания звукового компакт-диска
// ---------------------------------------------------
int PlayAudioTrack(DWORD dwLoc, DWORD dwSectorNum, int nCDUnit)
{
PlayAudio cmd;
memset(&cmd, 0, sizeof(PlayAudio));
cmd.rh.bSize = 22;
cmd.rh.bSubUnit = 0;
cmd.rh.bCmd = 132;
cmd.bMode = 0;
cmd.dwLoc = dwLoc;
cmd.dwSectorNum = dwSectorNum;
CallCDDriver(&cmd, nCDUnit);
return cmd.rh.wStatus;
}
// ---------------------------------------------------
// StopAudio
// Остановка проигрывания звукового компакт-диска
// ---------------------------------------------------
int StopAudio(int nCDUnit)
{
ReqHdr cmd;
memset(&cmd, 0, sizeof(ReqHdr));
cmd.bSize = 13;
cmd.bSubUnit = 0;
cmd.bCmd = 133;
CallCDDriver(&cmd, nCDUnit);
return (cmd.wStatus);
}
// ---------------------------------------------------
// DeviceOpen
// Открывание устройства
// ---------------------------------------------------
int DeviceOpen(int nCDUnit)
{
ReqHdr cmd;
memset(&cmd, 0, sizeof(ReqHdr));
cmd.bSize = 13;
cmd.bSubUnit = 0;
cmd.bCmd = 13;
CallCDDriver(&cmd, nCDUnit);
return (cmd.wStatus);
}
// ---------------------------------------------------
// DeviceClose
// Закрывание устройства
// ---------------------------------------------------
int DeviceClose(int nCDUnit)
{
ReqHdr cmd;
memset(&cmd, 0, sizeof(ReqHdr));
cmd.bSize = 13;
cmd.bSubUnit = 0;
cmd.bCmd = 14;
CallCDDriver(&cmd, nCDUnit);
return (cmd.wStatus);
}
// ---------------------------------------------------
// EjectCD
// Извлечение компакт-диска
// ---------------------------------------------------
int EjectCD(int nCDUnit)
{
IOCTL_Output cmd;
EjectDisk ed;
memset(&cmd, 0, sizeof(IOCTL_Output));
cmd.rh.bSize = 14;
cmd.rh.bSubUnit = 0;
cmd.rh.bCmd = 12;
cmd.bMediaDescriptor = 0;
cmd.lpTransferAddress = (DWORD)(void far *)&ed;
cmd.wDataSize = 1;
cmd.wStartSector = 0;
cmd.lpVolID = (DWORD)(void far *)NULL;
ed.bControl = 0;
CallCDDriver(&cmd, nCDUnit);
return cmd.rh.wStatus;
}
// ---------------------------------------------------
// CallCDDriver
// Вызов драйвера компакт-диска
// ---------------------------------------------------
void CallCDDriver(void *rh, int nCDUnit)
{
static union REGS rg;
static struct SREGS srg;
segread(&srg);
rg.x.ax = 0x1510;
rg.x.cx = nCDUnit;
rg.x.bx = FP_OFF(rh);
int86x(0x2f, &rg, &rg, &srg);
}
// ---------------------------------------------------
// GetCDLetters
// Заполнение массива номерами установленных
// в системе устройств чтения компакт-диска
// ---------------------------------------------------
void GetCDLetters(BYTE *bLetters)
{
static union REGS rg;
static struct SREGS srg;
segread(&srg);
rg.x.ax = 0x150d;
rg.x.bx = FP_OFF(bLetters);
int86x(0x2f, &rg, &rg, &srg);
}
// ---------------------------------------------------
// Преобразование адреса дорожки из формата Red book
// в формат Sierra
// ---------------------------------------------------
DWORD Red2Sierra(DWORD dwRedLoc)
{
BYTE bMin, bSec, bFrame;
bMin = (BYTE)((dwRedLoc >> 16) & 0xff);
bSec = (BYTE)((dwRedLoc >> 8) & 0xff);
bFrame = (BYTE)(dwRedLoc & 0xff);
return (DWORD)bMin * 75 * 60 + (DWORD)bSec * 75 +
(DWORD)bFrame - 150;
}
