Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

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


[Назад] [Содеожание] [Дальше]