;
; процедура инициализации резидентной программы без 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 ;перешлем
9
;
; модифицируем размер памяти текущей программы от сегмента
; 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 ; выполним
10
;
; укажем принадлежность полученной памяти для нового 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
1
ГРУППА ПРОГРАММИСТОВ 2B.
НЕСКОЛЬКО СЛОВ О ВИДЕОАДАПТЕРАХ.
В данной статье рассматриваются особенности работы
резидентных программ (например драйверов русского языка) с
основным и альтернативным видеоадаптером, описывается метод
идентификации основного и альтернативного видеоадаптера.
ЧТО ТАКОЕ ОСНОВНОЙ И АЛЬТЕРНАТИВНЫЙ ВИДЕОАДАПТЕР.
Обычно на ПЭВМ мы работаем только с одним дисплеем и,
соответственно, с одним видеоадаптером. Однако аппаратура
ПЭВМ допускает стандартное подключение дополнительного
видеоадаптера и дисплея. Такой дополнительный видеоадаптер
называется альтернативным. При этом не следует путать
альтернативные видеоадаптеры с нестандартными
видеоадаптерами. Первые поддерживаются стандартными
средствами BIOS, а вторые используются различными
программами (САПР или издательские системы) с помощью
нестандартных программных средств. Иначе говоря, на
стандартно подключенный видеоадаптер всегда можно перевести
вывод всех сообщений DOS и программ, которые для вывода
используют средства BIOS.
Не всякие виды видеоадаптеров могут быть подключены
одновременно к ПЭВМ. В таблице 1 рассматриваются допустимые
сочетания видеоадаптеров.
2
СОЧЕТАНИЯ ВИДЕОАДАПТЕРОВ.
Таблица 1.
ЪДДДДДДДДДДДДДДВДДДВДДДВДДДВДДДДВДДДВДДДВДДДДВДДДДДДДДДДДДД¬
¦ Видеоадаптер ¦MDA¦CGA¦EGA¦MCGA¦VGA¦HGC¦HGC+¦HGC In Color ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦MDA ¦ - ¦ + ¦ + ¦ + ¦ + ¦ - ¦ - ¦ - ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦CGA ¦ + ¦ - ¦ + ¦ - ¦ + ¦ + ¦ + ¦ + ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦EGA ¦ + ¦ + ¦ - ¦ - ¦ - ¦ + ¦ + ¦ + ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦MCGA ¦ + ¦ - ¦ - ¦ - ¦ + ¦ + ¦ + ¦ + ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦VGA ¦ + ¦ + ¦ - ¦ + ¦ - ¦ + ¦ + ¦ + ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦HGC ¦ - ¦ + ¦ + ¦ + ¦ + ¦ - ¦ - ¦ - ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦HGC+ ¦ - ¦ + ¦ + ¦ + ¦ + ¦ - ¦ - ¦ - ¦
ГДДДДДДДДДДДДДД†ДДД†ДДД†ДДД†ДДДД†ДДД†ДДД†ДДДД†ДДДДДДДДДДДДДґ
¦HGC In Color ¦ - ¦ + ¦ + ¦ + ¦ + ¦ - ¦ - ¦ - ¦
АДДДДДДДДДДДДДДБДДДБДДДБДДДБДДДДБДДДБДДДБДДДДБДДДДДДДДДДДДДЩ
Следует отметить, что к ПЭВМ не может быть подключено
два видеоадаптера, работающие одновременно в цветном или
монохромном режиме. Если один видеоадаптер работает в
цветном режиме, то другой должен работать в монохромном
режиме.
Рассмотрим теперь особенности определения текущего
видеоадаптера при работе резидентной программы.
ВИДЕОАДАПТЕР EGA.
Для определения активности видеоадаптера EGA достаточно
проверить бит активности EGA адаптера в области данных BIOS.
Признак активности видеоадаптера расположен в поле по
адресу 40h:87h. Если установлен флажок 08h, то это значит,
что в текущий момент видеоадаптер EGA не активен, поэтому
следует организовывать работу с учетом альтернативного
видеоадаптера. Приведем фрагмент кода для определения
активности видеоадаптера EGA.
mov ax,40h ;адресация данных
mov es,ax ; BIOS
test byte ptr es:[87h],08h ;EGA активен ?
jz EgaAct ;EGA активен
jmp NonEga ;EGA не активен
Следует отметить, что среди обилия видеоадаптеров EGA
существуют видеоадаптеры, позволяющие программно
переключаться в режим совместимости MDA и HGC. При этом они
зачастую корректируют адрес обработчика INT 10h. Поэтому,
перед проверкой активности видеоадаптера EGA, мы рекомендуем
3
убедиться, что EGA до сих пор существует на вашей ПЭВМ. Это
можно сделать путем считывания переключателей EGA по функции
INT 10h, AH=12h, BL=10h. Приведем фрагмент кода, для
выполнения этой функции.
mov ah,12h ;запрос
mov bl,10h ; переключателей
int 10h ; вызвать INT 10h
cmp bl,10h ;функция выполнена ?
je NonEga ; EGA не активен
jmp EgaAct ; EGA активен
ВИДЕОАДАПТЕРЫ VGA/MCGA.
Видеоадаптеры VGA и MCGA являются поколением
видеоадаптеров, анонсированных в ПЭВМ PS/2 фирмы IBM. В
настоящее время существует большое количество видеоадаптеров
VGA. Среди них есть видеоадаптеры, поддерживающие
расширенные графические и текстовые режимы.
Чтобы определить активность видеоадаптера VGA/MCGA
достаточно выполнить функцию INT 10h, AX=1A00h. Если функция
обеспечена, то в регистре AL будет значение 1Ah. В этом
случае в регистре BL Вы получите код основного, а в регистре
BH - код альтернативного дисплея в текущий момент времени.
Возможны следующие коды:
00h - отсутствует;
01h - монохром;
02h - CGA;
03h - резерв;
04h - EGA с цветным дисплеем;
05h - EGA с монохромным дисплеем;
06h - PGC с цветным дисплеем;
07h - VGA с монохромным дисплеем;
08h - VGA с цветным дисплеем;
09h - 0Ah - резерв;
0Bh - MCGA с монохромным дисплеем;
0Ch - MCGA с цветным дисплеем;
0Dh - FEh - резерв;
-1 - неизвестен.
Таким образом процесс определения активного
видеоадаптера для ПЭВМ, оборудованных видеоадаптерами VGA,
не представляет особых проблем.
4
Приведем фрагмент кода, определяющий активность
видеоадаптера VGA/MCGA.
mov ax,1a00h ;спросим код дисплея
int 10h ;выполним