Программирование драйвера экрана
.docxФедеральное Агентство по образованию
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)
Кафедра компьютерных систем в управлении и проектировании (КСУП)
ОТЧЁТ
по лабораторной работе № 1
«Программирование драйвера экрана»
Студент группы
2015
Содержание
1. Цель работы 2
2. Результаты выполнения программы 3
3. Выводы 4
Список используемой литературы 5
Приложение А – Листинг нерезидентного драйвера screen.asm 6
Приложение Б – Листинг основной программы lab1.asm 16
1. Цель работы
Требуется реализовать программно нерезидентный драйвер экрана с видеоадаптером CGA, логическая схема которого приведена на рисунке 40 [1]. Кроме того, требуется разработать прикладную программу, выполняющую вывод на экран фамилии и имени, и, возможно, другой информации, используя для вывода на экран написанный драйвер.
Исходя из последних двух цифр в пароле и общего кол-ва заданий, мне выпадает вариант № 17.
Цвет символов: серый.
Цвет фона: ярко-красный.
2. Результаты выполнения программы
3. Выводы
В ходе выполнения данной работы был написан и отлажен модуль драйвер экрана, а также разработана прикладная программа, использующая его интерфейс для вывода символов на экран монитора.
Список используемой литературы
-
Одиноков В. В. ЭВМ и вычислительные системы. Однопрограммные системы: Учебное пособие. – Томск: Томский межвузовский центр дистанционного образования, 2002. – 133 с.
2. http://www.escolero.ru/shop/13/Programmirovanie_drajvera_ekrana/
Приложение А – Листинг нерезидентного драйвера screen.asm
code_seg segment public
assume cs:code_seg
public sc_x_coord, sc_y_coord, sc_symbol, sc_attributes ; переменные, доступные другим модулям
public sc_init, sc_print_symbol, sc_print_string ; функции, доступные другим модулям
; данные
sc_video_addr equ 0B800h ; адрес начала видеопамяти
; публичные переменные
sc_x_coord db 0 ; координата X (номер строки)
sc_y_coord db 0 ; координата Y (номер столбца)
sc_symbol db 0 ; символ
sc_attributes db 0 ; атрибуты
;-------------------------------------------------------------------------------
; Процедура инициализации драйвера экрана
; ничего не получает, не возвращает
; заполняет видеопамять заданными символами (пробел с цветом фона)
sc_init proc near
push ES ; сохраняем значение регистров на стеке
push AX
push DI
push CX
push DX
; очистка видеопамяти (заполение символом пробела)
mov AL, ' ' ; символ пробела
mov AH, 01001000b ; атрибуты
mov CX, sc_video_addr
mov ES, CX ; адрес начала видеопамяти
xor DI, DI ; итератор цикла
cycle1: ; цикл заполнения памяти
cmp DI, 4000 ; 4000 байт (по два байта на символ)
jge end_of_cycle1
cld ; очистка флагов направления
stosw ; [ES:DI] = AX
jmp cycle1
end_of_cycle1:
; Установка размера курсора
; начало курсора
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 10 ; регистр "начало курсора"
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, 0 ; начало = 0
out DX, AL ; пишем в регистр "начало курсора"
; конец курсора
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 11 ; регистр "конец курсора"
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, 15 ; конец равен 15
out DX, AL ; пишем в регистр "конец курсора"
; установка позиции курсора
; старший байт
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 14 ; регистр "адрес курсора" (ст.)
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, 1 ; устанавливаем старший байт (например, 1)
out DX, AL ; пишем в регистр "адрес курсора" (ст.)
; младший байт
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 15 ; регистр "адрес курсора" (мл.)
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, 1 ; устанавливаем младший байт (например, 1)
out DX, AL ; пишем в порт
pop DX
pop CX ; восстанавливаем регистры
pop DI
pop AX
pop ES
ret ; возврат из процедуры
sc_init endp
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Процедура вывода символа
; Выводит символ sc_symbol с атрибутами (sc_attributes)
; по координатам(sc_x_coord, sc_y_coord) и перемещает курсор
; изменяет переменные sc_x_coord и sc_y_coord
; в случае, если строка > 25 - оставляем 25 и производим скроллинг (сдвиг)
; ничего не возвращает
sc_print_symbol proc near
push ES ; сохраняем значения регистров на стеке
push AX
push DI
push CX
push DX
push BX
push SI
mov AL, sc_symbol ; в AL - символ
cmp AL, 0Dh ; сравним с возвратом каретки
je change_coordinates ; если равен - только установка новых координат
cmp AL, 0Ah ; сравним с переводом строки
je change_coordinates ; если равен - только установка координат
; если нужно изменить символ в видеопамяти
mov CX, sc_video_addr
mov ES, CX ; адрес начала видеопамяти
xor AX, AX
; вычисляем адрес в памяти по координатам
mov AL, sc_x_coord
mov CL, 80
mul CL ; AX = 80*sc_x_coord
xor CX, CX
mov CL, sc_y_coord
add AX, CX ; AX = 80*sc_x_coord + sc_y_coord
shl AX, 1 ; AX = (80*sc_x_coord + sc_y_coord) * 2
mov DI, AX ; DI = (80*sc_x_coord + sc_y_coord) * 2
; устанавливаем символ и атрибуты
mov AL, sc_symbol ; символ
mov AH, sc_attributes ; атрибуты
cld ; очистка флагов направления
stosw ; [ES:DI] = AX
; изменим sc_x_coord и sc_y_coord
change_coordinates:
mov AL, sc_symbol
cmp AL, 0Dh ; возврат каретки
jne not_cr ; переход на сравнение с Переводом строки
mov AL, 0
mov sc_y_coord, AL ; то sc_y_coord = 0
jmp set_cursor_position
not_cr:
cmp AL, 0Ah ; новая строка
jne not_lf ; если не равно, переход
jmp only_inc_x ; переход на след. строку
not_lf: ; не перевод строки
mov AL, sc_y_coord
inc AL ; увеличим кооринату y
cmp AL, 80
jge next_row ; если >= 80 - следующая строка
mov sc_y_coord, AL
jmp set_cursor_position ; изменили sc_y_coord, перейдем к установке курсора
next_row: ; если нужен перевод строки и возврат каретки
mov AL, 0
mov sc_y_coord, AL ; запиываем новое значение
only_inc_x: ; если нужен только перевод строки
mov AL, sc_x_coord
inc AL ; увеличим кооринату x
cmp AL, 25 ; если >= 25 - произведем сдвиг экрана
jge scroll_screen ; переход к скроллингу
mov sc_x_coord, AL ; сохраняем значение
jmp set_cursor_position ; изменили sc_x_coord, перейдем к установке курсора
;====================================================================
scroll_screen:
; значение sc_x_coord не изменяем
; сдвиг экрана на строку вверх
push DS ; сохраняем DS
mov CX, sc_video_addr
mov ES, CX ; адрес начала видеопамяти
mov DS, CX
xor AX, AX
mov SI, 160
xor DI, DI
shift_cycle:
cmp SI, 4000 ; последнюю строку оставляем
jge end_of_shift_cycle
cld ; очистка флагов направления
movsw ; [ES:DI] = [DS:SI]
jmp shift_cycle
end_of_shift_cycle:
pop DS ; восстанавливаем DS
; очистка последней строки
mov CX, sc_video_addr
mov ES, CX ; адрес начала видеопамяти
mov AL, ' ' ; символ пробела
mov AH, sc_attributes ; атрибуты
mov DI, 4000 - 160
clean_row_cycle: ; цикл заполнения памяти
cmp DI, 4000 ; 2000 * 2 байт
jge end_of_clean_row_cycle
cld ; очистка флагов направления
stosw ; [ES:DI] = AX
jmp clean_row_cycle
end_of_clean_row_cycle:
;====================================================================
set_cursor_position:
; расчет координат = 80 * sc_x_coord + sc_y_coord
mov AL, sc_x_coord
mov CL, 80
mul CL
xor CX, CX
mov CL, sc_y_coord
add AX, CX
mov CX, AX ; CX = новые координаты
; установка позиции курсора на основе sc_x_coord и sc_y_coord
; старший байт
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 14 ; регистр адрес курсора (ст.)
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, CH ; устанавливаем старший байт
out DX, AL ; пишем в регистр адрес курсора (ст.)
; младший байт
mov DX, 3D4h ; индексный регистр указывает на
mov AL, 15 ; регистр адрес курсора (мл.)
out DX, AL ; пишем в порт
inc DX ; 3D5h - управляющий регистр
mov AL, CL ; устанавливаем младший байт
out DX, AL ; пишем в порт
exit_print_symbol:
pop SI
pop BX
pop DX
pop CX ; восстанавливаем регистры
pop DI
pop AX
pop ES
ret ; возврат из процедуры
sc_print_symbol endp
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
; Процедура вывода последовательности символов
; в DS:BX - адрес данной строки
; ничего не возвращает
; выводит символы с помощью процедуры sc_print_symbol
; пока не встретится нулевой байт
sc_print_string proc near
push AX
push BX ; сохраняем регистры, значение которых меняется в данной процедуре
print_cycle: ; цикл вывода строки
mov AL, byte ptr[BX]
cmp AL, '$' ; сравниваем текущий символ с нулевым байтом
je end_of_print_cycle ; если символ - ноль - заканчиваем вывод
mov sc_symbol, AL ; помещаем текущий символ
call sc_print_symbol ; вызов процедуры вывода символа
inc BX ; увеличиваем индекс
jmp print_cycle
end_of_print_cycle:
pop BX ; восстанавливаем регистры
pop AX
ret
sc_print_string endp
;-------------------------------------------------------------------------------
code_seg ends
end
Приложение Б – Листинг основной программы lab1.asm
code_seg segment public
assume cs:code_seg
org 100h
; Внешние переменные и процедуры (определены в модуле "Драйвер экрана")
extrn sc_x_coord:byte, sc_y_coord:byte, sc_symbol:byte, sc_attributes:byte
extrn sc_init:near, sc_print_symbol:near, sc_print_string:near
begin: ; точка входа
call sc_init ; вызываем процедуру инициализации экрана
mov sc_x_coord, 0 ; устанавливаем координаты
mov sc_y_coord, 0 ; устанавливаем координаты
mov sc_attributes, 01001000b ; устанавливаем атрибуты символов
mov BX, offset txt ; адрес начала выводимой строки
call sc_print_string ; вывод строки
mov AH, 00
int 16h ; ждем нажатия клавиши
mov AX, 4c00h
int 21h ; завершаем программу
; данные
txt db "Лабораторная работа #1", 13, 10, "Программирование драйвера экрана", 13, 10,13, 10,"Иванов Иван Иванович", 13, 10, "666У-б", 13, 10, "г.Урюпинск$"
code_seg ends
end begin