| Аппаратное обеспечение 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
 | 


![[Назад]](../../prev.gif)
![[Содеожание]](../../sod.gif)
![[Дальше]](../../next.gif)