Аппаратное обеспечение IBM PC© Александр Фролов, Григорий ФроловТом 2, книга 1, М.: Диалог-МИФИ, 1992. 10.5. Примеры программПервая программа демонстрирует проверку подключения драйвера и использование его основных функций:
include sysp.inc
.MODEL tiny
DOSSEG
.STACK 100h
.DATA
msg DB 13,10,"Работа с драйвером HIMEM.SYS", 13, 10
DB "Copyright ©Frolov A.,1991",13,10,13,10
DB "$"
noHMM DB 13,10
DB "Драйвер HIMEM.SYS не установлен",13,10,"$"
yesHMM DB 13,10,"Драйвер HIMEM.SYS установлен, ", "$"
ver1 DB "версия: ", "$"
ver2 DB ", номер модификации: ", "$"
errmsg DB 13,10,"Ошибка с кодом ", "$"
okmsg DB 13,10,"Успех!!!", "$"
hmareq DB 13,10,"Запрашиваем область HMA", "$"
hmarel DB 13,10,"Освобождаем область HMA", "$"
enA20 DB 13,10,"Открываем линию A20", "$"
dsA20 DB 13,10,"Закрываем линию A20", "$"
loc_enA20 DB 13,10,"Локальный доступ к линии A20","$"
loc_dsA20 DB 13,10,"Закрываем локальный доступ"
DB " к линии A20", "$"
check_A20 DB 13,10,"Проверяем доступность "
DB "линии A20", "$"
free_ext_mem DB 13,10,"Всего расширенной "
DB "памяти, Кбайт: ", "$"
max_ext_block DB 13,10,"Максимальный участок "
DB "свободной"
DB " расширенной памяти, Кбайт: ", "$"
HMMEntry dd ?
.CODE
.STARTUP
mov ah, 9h ; Выводим заголовок
mov dx, OFFSET msg
int 21h
; Проверяем, установлен ли драйвер HIMEM.SYS
mov ax, 4300h
int 2fh
cmp al, 80h
je HMM_installed
; Если не установлен, выводим сообщение и завершаем
; работу программы
mov ah, 9h
mov dx, OFFSET noHMM
int 21h
jmp terminate
HMM_installed:
mov ah, 9h
mov dx, OFFSET yesHMM
int 21h
; Получаем адрес управляющей функции драйвера
mov ax, 4310h
int 2fh
mov word ptr cs:[HMMEntry][0], bx
mov word ptr cs:[HMMEntry][2], es
; Получаем номер версии
mov ah, 9h
mov dx, OFFSET ver1
int 21h
mov ax,0
call cs:[HMMEntry]
; Выводим номер версии на экран
call Print_word
mov ah, 9h
mov dx, OFFSET ver2
int 21h
mov ax, bx
call Print_word
; Запрашиваем область HMA
mov ah, 9h
mov dx, OFFSET hmareq
int 21h
mov ax,0100h
mov dx,0ffffh
call cs:[HMMEntry]
or ax, ax
jnz hmareq_ok
jmp error
hmareq_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Открываем линию A20
mov ah, 9h
mov dx, OFFSET enA20
int 21h
mov ax,0300h
call cs:[HMMEntry]
or ax, ax
jnz enA20_ok
jmp error
enA20_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Закрываем линию A20
mov ah, 9h
mov dx, OFFSET dsA20
int 21h
mov ax,0400h
call cs:[HMMEntry]
or ax, ax
jnz dsA20_ok
jmp error
dsA20_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Освобождаем область HMA
mov ah, 9h
mov dx, OFFSET hmarel
int 21h
mov ax,0200h
call cs:[HMMEntry]
or ax, ax
jz error
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Получаем локальный доступ к линии A20
mov ah, 9h
mov dx, OFFSET loc_enA20
int 21h
mov ax,0500h
call cs:[HMMEntry]
or ax, ax
jz error
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Проверяем линию A20
mov ah, 9h
mov dx, OFFSET check_A20
int 21h
mov ax,0700h
call cs:[HMMEntry]
or ax, ax
jz error
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Определяем размер свободной расширенной памяти
mov ah, 9h
mov dx, OFFSET free_ext_mem
int 21h
mov ax,0800h
call cs:[HMMEntry]
push ax
mov ax, dx
call Print_word
mov ah, 9h
mov dx, OFFSET max_ext_block
int 21h
pop ax
call Print_word
; Освобождаем линию A20
mov ah, 9h
mov dx, OFFSET loc_dsA20
int 21h
mov ax,0600h
call cs:[HMMEntry]
or ax, ax
jz error
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
jmp terminate
error:
push bx
mov ah, 9h
mov dx, OFFSET errmsg
int 21h
pop ax
call Print_word
terminate:
.EXIT 0
; Вывод на экран содержимого регистра AX
Print_word proc near
;--------------------
push ax
push bx
push dx
;
push ax
mov cl,8
rol ax,cl
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop ax
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop dx
pop bx
pop ax
ret
Print_word endp
;
Byte_to_hex proc near
;--------------------
; al - input byte
; dx - output hex
;--------------------
push ds
push cx
push bx
;
lea bx,tabl
mov dx,cs
mov ds,dx
;
push ax
and al,0fh
xlat
mov dl,al
;
pop ax
mov cl,4
shr al,cl
xlat
mov dh,al
;
pop bx
pop cx
pop ds
ret
;
tabl db '0123456789ABCDEF'
Byte_to_hex endp
;
END
Теперь приведем пример программы, использующей область HMA для выполнения процедуры генерации звукового сигнала. Программа получает доступ к области HMA, копирует в нее процедуру генерации звукового сигнала и вызывает эту процедуру с помощью межсегментной команды call:
include sysp.inc
.MODEL tiny
DOSSEG
.STACK 100h
.DATA
msg DB 13,10,"Работа в области HMA", 13, 10
DB "Copyright ©Frolov A.,1991",13,10,13,10
DB "$"
noHMM DB 13,10,"Драйвер HIMEM.SYS "
DB "не установлен", 13, 10, "$"
yesHMM DB 13,10,"Драйвер HIMEM.SYS установлен, ","$"
errmsg DB 13,10,"Ошибка с кодом ", "$"
okmsg DB 13,10,"Успех!!!", "$"
hmareq DB 13,10,"Запрашиваем область HMA", "$"
hmarel DB 13,10,"Освобождаем область HMA", "$"
enA20 DB 13,10,"Открываем линию A20", "$"
dsA20 DB 13,10,"Закрываем линию A20", "$"
HMMEntry dd ?
HMAStart dd ?
.CODE
.STARTUP
mov ah, 9h ; Выводим заголовок
mov dx, OFFSET msg
int 21h
; Проверяем, установлен ли драйвер HIMEM.SYS
mov ax, 4300h
int 2fh
cmp al, 80h
je HMM_installed
; Если не установлен, выводим сообщение и завершаем
; работу программы
mov ah, 9h
mov dx, OFFSET noHMM
int 21h
jmp terminate
HMM_installed:
mov ah, 9h
mov dx, OFFSET yesHMM
int 21h
; Получаем адрес управляющей функции драйвера
mov ax, 4310h
int 2fh
mov word ptr cs:[HMMEntry][0], bx
mov word ptr cs:[HMMEntry][2], es
; Запрашиваем область HMA
mov ah, 9h
mov dx, OFFSET hmareq
int 21h
mov ax,0100h
mov dx,0ffffh
call cs:[HMMEntry]
or ax, ax
jnz hmareq_ok
jmp error
hmareq_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Открываем линию A20
mov ah, 9h
mov dx, OFFSET enA20
int 21h
mov ax,0300h
call cs:[HMMEntry]
or ax, ax
jnz enA20_ok
jmp error
enA20_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Записываем в двойное слово HMAStart
; адрес начала облсти HMA
mov word ptr cs:[HMAStart][0], 0010h
mov word ptr cs:[HMAStart][2], 0ffffh
; Копируем в область HMA процедуру, которая
; будет там выполняться
cld
lea si, begin_HMA_code
mov di, 0010h
mov ax, cs
mov ds, ax
mov ax, 0ffffh
mov es, ax
mov cx, HMA_code_size
rep movsb
; Вызываем процедуру, находящуюся в области HMA
call cs:[HMAStart]
; Закрываем линию A20
mov ah, 9h
mov dx, OFFSET dsA20
int 21h
mov ax,0400h
call cs:[HMMEntry]
or ax, ax
jnz dsA20_ok
jmp error
dsA20_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Освобождаем область HMA
mov ah, 9h
mov dx, OFFSET hmarel
int 21h
mov ax,0200h
call cs:[HMMEntry]
or ax, ax
jz error
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
jmp terminate
error:
push bx
mov ah, 9h
mov dx, OFFSET errmsg
int 21h
pop ax
call Print_word
terminate:
.EXIT 0
; Вывод на экран содержимого регистра AX
Print_word proc near
;--------------------
push ax
push bx
push dx
;
push ax
mov cl,8
rol ax,cl
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop ax
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop dx
pop bx
pop ax
ret
Print_word endp
;
Byte_to_hex proc near
;--------------------
; al - input byte
; dx - output hex
;--------------------
push ds
push cx
push bx
;
lea bx,tabl
mov dx,cs
mov ds,dx
;
push ax
and al,0fh
xlat
mov dl,al
;
pop ax
mov cl,4
shr al,cl
xlat
mov dh,al
;
pop bx
pop cx
pop ds
ret
;
tabl db '0123456789ABCDEF'
Byte_to_hex endp
; Эта процедура предназначена для
; выполнения в области HMA.
; Она просто три раза генерирует
; звуковой сигнал.
begin_HMA_code:
BEEP
BEEP
BEEP
retf
end_HMA_code:
; Здесь записана длина процедуры,
; предназначенной для выполнения в
; области HMA
HMA_code_size dw $-begin_HMA_code
END
В программе использована макрокоманда BEEP, описанная в файле sysp.inc:
; Макро для выдачи звукового сигнала
BEEP MACRO
mov bx,0
mov ax, 0E07h
int 10h
ENDM
Следующая программа демонстрирует использование функции копирования. Сообщение копируется из области основной памяти в область расширенной памяти, а затем обратно в область основной памяти, но в другое место:
include sysp.inc
ExtMemMoveStruct struc
@Length dd ? ; количество пересылаемых байтов
SourceHandle dw ? ; индекс исходного блока
SourceOffset dd ? ; смещение в исходном блоке
DestHandle dw ? ; индекс блока-назначения
DestOffset dd ? ; смещение в блокe
ExtMemMoveStruct ends
.MODEL tiny
DOSSEG
.STACK 100h
.DATA
movestr ExtMemMoveStruct <0,0,0,0,0>
msg DB 13,10,"Использование блоков EMB", 13, 10
DB "Copyright ©Frolov A.,1991",13,10,13,10
DB "$"
noHMM DB 13,10,"Драйвер HIMEM.SYS не установлен",13,10,"$"
yesHMM DB 13,10,"Драйвер HIMEM.SYS установлен, ","$"
errmsg DB 13,10,"Ошибка с кодом ", "$"
okmsg DB 13,10,"Успех!!!", "$"
free_ext_mem DB 13,10,"Всего расширенной памяти, Кбайт: ","$"
max_ext_block DB 13,10,"Максимальный участок свободной"
DB " расширенной памяти, Кбайт: ", "$"
getEMBmsg DB 13,10,"Получаем блок EMB","$"
freeEMBmsg DB 13,10,"Освобождаем блок EMB","$"
copymsg DB 13,10,"Копируем блок данных в область EMB","$"
copymsg1 DB 13,10,"Копируем блок данных обратно","$"
testmsg DB 13,10,13,10,"Сообщение для копирования"
DB " в область EMB","$"
len_testmsg DW $-testmsg
; Буфер для копирования сообщения
testbuf DB 512 dup(?)
HMMEntry dd ?
EMBHandle dw ?
.CODE
.STARTUP
mov ah, 9h ; Выводим заголовок
mov dx, OFFSET msg
int 21h
; Проверяем, установлен ли драйвер HIMEM.SYS
mov ax, 4300h
int 2fh
cmp al, 80h
je HMM_installed
; Если не установлен, выводим сообщение и завершаем
; работу программы
mov ah, 9h
mov dx, OFFSET noHMM
int 21h
jmp terminate
HMM_installed:
mov ah, 9h
mov dx, OFFSET yesHMM
int 21h
; Получаем адрес управляющей функции драйвера
mov ax, 4310h
int 2fh
mov word ptr cs:[HMMEntry][0], bx
mov word ptr cs:[HMMEntry][2], es
; Определяем размер свободной расширенной памяти
mov ah, 9h
mov dx, OFFSET free_ext_mem
int 21h
mov ax,0800h
call cs:[HMMEntry]
push ax
mov ax, dx
call Print_word
mov ah, 9h
mov dx, OFFSET max_ext_block
int 21h
pop ax
call Print_word
; Получаем блок EMB
mov ah, 9h
mov dx, OFFSET getEMBmsg
int 21h
mov ax,0900h
mov dx,1h
call cs:[HMMEntry]
or ax, ax
jnz getemb_ok
jmp error
getemb_ok:
mov EMBHandle, dx
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Копируем строку testmsg в блок EMB
mov ah, 9h
mov dx, OFFSET copymsg
int 21h
; Заполняем управляющую структуру
; Длина копируемого массива памяти
mov ax, word ptr len_testmsg
mov word ptr movestr.@Length, ax
; Индекс основной памяти, должен быть = 0
mov ax, 0
mov word ptr movestr.SourceHandle, ax
; Задаем сегмент:смещение копируемого сообщения
mov ax, OFFSET testmsg
mov word ptr [movestr.SourceOffset][0], ax
mov ax, cs
mov word ptr [movestr.SourceOffset][2], ax
; Задаем индекс EMB, в который будем копировать
; сообщение из основной памяти
mov ax, EMBHandle
mov movestr.DestHandle, ax
; Копируем в начало EMB, поэтому
; смещение = 0
mov ax, 0
mov word ptr [movestr.DestOffset][0], ax
mov word ptr [movestr.DestOffset][2], ax
; Загружаем адрес управляющей структуры в DS:SI
mov ax, cs
mov ds, ax
mov ax, OFFSET movestr
mov si, ax
mov ax,0B00h
; Вызываем функцию копирования
call cs:[HMMEntry]
or ax, ax
jnz moveemb_ok
jmp error
moveemb_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Копируем сообщение обратно из блока EMB
; в буфер testbuf, расположенный в основной
; памяти
mov ah, 9h
mov dx, OFFSET copymsg1
int 21h
; Подготавливаем управляющую структуру
mov ax, word ptr len_testmsg
mov word ptr movestr.@Length, ax
mov ax, 0
mov word ptr movestr.DestHandle, ax
mov ax, OFFSET testbuf
mov word ptr [movestr.DestOffset][0], ax
mov ax, cs
mov word ptr [movestr.DestOffset][2], ax
mov ax, EMBHandle
mov movestr.SourceHandle, ax
mov ax, 0
mov word ptr [movestr.SourceOffset][0], ax
mov word ptr [movestr.SourceOffset][2], ax
; Выполняем копирование
mov ax, cs
mov ds, ax
mov ax, OFFSET movestr
mov si, ax
mov ax,0B00h
call cs:[HMMEntry]
or ax, ax
jnz move1emb_ok
jmp error
move1emb_ok:
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
; Выводим скопированное сообщение на экран
; для проверки
mov ah, 9h
mov dx, OFFSET testbuf
int 21h
; Освобождаем блок EMB
mov ah, 9h
mov dx, OFFSET freeEMBmsg
int 21h
mov ax,0A00h
mov dx,EMBHandle
call cs:[HMMEntry]
or ax, ax
jnz freeemb_ok
jmp error
freeemb_ok:
mov EMBHandle, dx
mov ah, 9h
mov dx, OFFSET okmsg
int 21h
jmp terminate
error:
push bx
mov ah, 9h
mov dx, OFFSET errmsg
int 21h
pop ax
call Print_word
terminate:
.EXIT 0
; Вывод на экран содержимого регистра AX
Print_word proc near
;--------------------
push ax
push bx
push dx
;
push ax
mov cl,8
rol ax,cl
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop ax
call Byte_to_hex
mov bx,dx
@@out_ch bh
@@out_ch bl
;
pop dx
pop bx
pop ax
ret
Print_word endp
;
Byte_to_hex proc near
;--------------------
; al - input byte
; dx - output hex
;--------------------
push ds
push cx
push bx
;
lea bx,tabl
mov dx,cs
mov ds,dx
;
push ax
and al,0fh
xlat
mov dl,al
;
pop ax
mov cl,4
shr al,cl
xlat
mov dh,al
;
pop bx
pop cx
pop ds
ret
;
tabl db '0123456789ABCDEF'
Byte_to_hex endp
END
|

