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