Н А Ц И О Н А Л Ь Н Ы Й ТЕХНИЧЕСКИЙ У НИ В ЕР С И ТЕТ
" ХАР ЬКОВСКИЙ ПОЛИ ТЕХНИЧЕСКИЙ ИН СТИ ТУТ "
АРХИТЕКТУРА КОМПЬЮТЕРОВ
Лабораторный практикум
Утверждено редакционно-издательским
советом университета,
протокол № 2 от 25.06.2015 г.
Харьков
НТУ "ХПИ"
2016
УДК 004.3(075)
ББК 32.973–02я7
П 42
Поворознюк А.И.
П42 Архитектура компьютеров : лаб. практикум / А. И. Поворознюк,
Н. В. Мезенцев, О.А. Поворознюк,. – Харьков : Курсор, 2016. – 131 с.
ISBN 978-966-8944-80-2
В данном издании приведены методические указания к лабораторным работам
1–15, которые включают работы по определению конфигурации ПК, управлению
таймером и звуком, клавиатурой, накопителями на магнитных дисках, управлению
видеомонитором в текстовом и графическом режимах.
Предназначено для студентов всех специальностей бакалаврата 6.050102
"Компьютерная инженерия", а также может быть полезное как для начинающих, так и
для опытных программистов при создании эффективного программного обеспечения.
УДК 004.3(075)
ББК 32.973–02я7
СОДЕРЖАНИЕ
ВВЕДЕНИЕ.............................................................................................................4
ЛИТЕРАТУРА....................................................................................................130
4
ВВЕДЕНИЕ
Лабораторная работа 1
Затем нужно указать имя и описание данной рабочей машины (рис. 1.18).
14
Лабораторная работа 2
Ячейка 15h содержит младший байт, а ячейка 16h – старший байт размера
основной памяти в килобайтах.
if(b and $01)=0 then writeln( '0-й разряд байта b содержит 0')
else writeln(' 0-й разряд байта b содержит 1');
24
2.4.2. На языке С.
char CPUVendor[12];
asm {
mov eax,0h;
db 0fh,0A2h
mov dword ptr CPUVendor,ebx
mov dword ptr CPUVendor+4,edx
mov dword ptr CPUVendor+8,ecx
}
Лабораторная работа 3
Прерывания
Аппаратные Программные
Внешние Внутренние
Маскируемые Немаскируемые
2
Обнулить флаги
IF и TF
3
Поместить в стек
значение регистра CS
Команда INT 4
(Interrupt) Присвоить адресу век-
тора прерываний N*4
5
Загрузить старшее слово
вектора в CS
6
Поместить в стек
значение регистра IP
7
Загрузить младшее слово
вектора в IP
8
Выполнить действия
обработчика прерываний
9
Извлечь из стека и
загрузить значение IP
10
Команда IRET Извлечь из стека и
(Interrupt return) загрузить значение CS
11
Извлечь из стека и загрузить
значение регистра флагов
конец
ofs_:= MemW[0000:4*9];
Memw[0000:4*$60+2]:=Seg(Int9d);
begin
.....
asm
Cli {прерывания запрещены}
end
.....
asm
Sti {прерывания разрешены}
end
......
procedure NewIntr(Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS,
ES, BP : Word); Interrupt;
begin
...
end.
Примечание:
– имя процедуры задается пользователем;
– любое число параметров (в том числе и все) в процедуре можно
опускать, но только подряд начиная с начала.
Вызов пользовательской процедуры обработки прерывания
осуществляется с помощью процедуры Intr (см. п. 3.5.1.2). Предварительно
адрес процедуры пользователя должен быть занесен в таблицу векторов
прерывания в соответствии с выбранным номером прерывания либо путем
37
SetIntVec(IntNo:byte; Vector:pointer),
где: IntNo задает номер прерывания (0...255) и Vector задает адрес (при
задании адреса можно воспользоваться оператором @ или функцией Addr).
3.5.2. На языке С.
*int9_p=*adr_p;
нк := нс mod 8,
Лабораторная работа 4
Переключатели +5В
клавиатуры
...
. . .
D 8048 T0
. 0 P26 cloc
. D1
. T1
D2 data
P27
P
10
P11
P
20 ГСИ
P21
Х1
Команда состоит из двух байтов. Первый байт: код команды – ЕDh; Для
включения или выключения светодиодов после кода команды (EDh) через 60h
порт посылается байт данных, биты которого имеют следующее назначения
(табл. 4.2):
Биты Значение
0 1 – включить ScrollLock;
1 1 – включить NumLock;
2 1 – включить CapsLock;
3-7 не используются.
1
начало
2
Для предотвращения чтения скан-
Задержка 100 мс кодов отжатия клавиш Ctrl и F9 при
запуске программы
3
I = 1,2
9
4 конец
Чтение из порта 60h
скан-кода
5
Чтение из порта 60h
скан-кода
да 6
Скан-коды совпадают?
нет
7
"новый" скан-код
8
"старый" скан-код =
"новому"
Лабораторная работа 5
15 0
0040:003Ch Содержимое ячейки буфера
Физ. конец буфера F
F 0040:003Ah 15 87 0
U 0040:0038h Скан-код ASCII
B 0040:0036h
Если ASCII-код равен нулю, то
0040:0034h
вместо скан-кода указывается
расширенный код.
0040:0022h
R 0040:0020h
Физ. начало буфера E 0040:001Eh
Указатель хвоста 22 0040:001Ch
Указатель начала 36 0040:001Ah
1
начало
да 2
Буфер пуст?
нет
3
Чтение байта по адресу Чтение ASCII-кода
начала буфера нажатой клавиши
4
Чтение байта по адресу Чтение скан-кода, если ASCII-код ≠0,
начала буфера иначе номера расширенного кода
5
ASCII и скан-код
6
Коррекция указателя
начала буфера
нет
Ctrl+Break?
да
8
конец
5.4.2. На языке С.
Лабораторная работа 6
Замечания:
Значения цилиндра и сектора занимают 10 и 6 бит соответственно.
Формат слова, задающего значения цилиндра и сектора приведен на рис. 6.1
(ц – разряды значения цилинда, Ц – старший разряд; с – разряды значения
сектора, С – старший разряд).
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
ц ц ц ц ц ц ц ц Ц ц С с с с с с
переменной Registers;
– объявить переменную этого типа, например, reg:Registers;
– к регистрам микропроцессора обращаться, как reg.ah, reg.al и т.д.;
– процедуру прерывания 13h вызывать следующим образом:
Intr($13,reg).
var
sect:array[0..511] of byte;
reg.es:=Seg(sect);
reg.bx:=Ofs(sect);
6.4.2. На языке С.
#include <dos.h>
int86x(0x13,&in,&out,&sr).
sr.es=FP_SEG(buf);
in.x.bx=FP_OFF(buf);
Лабораторная работа 7
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
часы минуты сек/2
15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
год месяц день
– атрибуты;
– номер начального кластера;
– время и дату создания;
– размер.
7.3.4. Сравнить полученную информацию о файлах с информацией,
предоставляемой операционной системой.
Intr($13,reg).
var
sec_cat:array[1..16] of record
name :array[1..8] of char;
name_e :array[1..3] of char;
atr :byte;
rez :array[1..10] of byte;
time,
date,
n_clast :word;
size :longint
end;
reg.es:=Seg(sec_cat);
reg.bx:=Ofs(sec_cat);
65
#include <dos.h>
int86x(0x13,&in,&out,&sr).
struct sec_cat{
unsigned char name[8];
unsigned char name_e[3];
unsigned char atr;
unsigned char rez[10];
unsigned int time;
unsigned int date;
unsigned int n_clast;
unsigned long size ;
};
и определить массив структур
sr.es=FP_SEG(sec);
in.x.bx=FP_OFF(sec);
Лабораторная работа 8
элементы FAT
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
ID FF 03 04 05 FF 00 00 09 0A 0B 15 00 00 00 00
10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
00 00 00 00 00 16 17 19 FF7 1A 1B FFF 00 00 00 00
var
fat:array[0..511] of byte;
reg.es:=Seg(sect);
reg.bx:=Ofs(sect);
70
8.4.2. На языке С.
#include <dos.h>
sr.es=FP_SEG(buf);
in.x.bx=FP_OFF(buf);
Лабораторная работа № 9
Сброс контроллера
прерываний
IRET
таймера при достижении счетчиком CE нуля тем или иным способом меняется
выходной сигнал OUT.
Буферный регистр OL предназначен для запоминания текущего
содержимого регистра счетчика CE без остановки процесса счета. После
запоминания буферный регистр доступен программе для чтения.
Регистр констант пересчета CR может загружаться в регистр счетчика,
если это требуется в текущем режиме работы таймера.
Возможны 6 режимов работы таймера. Они разделяются на три типа:
• режимы 0 и 4- однократное выполнение функций;
• режимы 1 и 5 - работа с перезапуском;
• режимы 2 и 3 - работа с автозагрузкой.
В режиме однократного выполнения функций перед началом счета
содержимое регистра констант CR переписывается в регистр счетчика CE по
сигналу CLOCK, если сигнал GATE установлен в 1. В дальнейшем
содержимое регистра CE уменьшается по мере прихода сигналов CLOCK.
Процесс счета можно приостановить, если подать на вход GATE уровень
логического 0. Если затем на вход GATE подать 1, счет будет продолжен
дальше. Для повторения выполнения функции необходима новая загрузка
регистра CR, т.е. повторное программирование таймера.
При работе с перезапуском не требуется повторного программирования
таймера для выполнения той же функции. По фронту сигнала GATE значение
константы из регистра CR вновь переписывается в регистр СЕ, даже если
текущая операция не была завершена.
В режиме автозагрузки регистр CR автоматически переписывается в в
регистр CE после завершения счета. Сигнал на выходе OUT появляется только
при наличии на входе GATE уровня логической 1. Этот режим используется
для создания программируемых импульсных генераторов и генераторов
прямоугольных импульсов (меандров).
В компьютерах IBM PC/XT/AT/PS2 задействованы все три канала
таймера.
Канал 0 используется операционной системой для формирования
временных интервалов. Этот канал работает в режиме 3 и используется как
генератор импульсов с частотой примерно 18,2 Гц. Именно эти импульсы
вызывают аппаратное прерывание INT 8h.
Канал 1 используется для регенерации содержимого динамической
памяти компьютера, поэтому его лучше не трогать. Выходная линия канала
OUT связана с микросхемой прямого доступа к памяти (DMA), и ее импульс
заставляет DMA регенерировать память.
Канал 2 связан с громкоговорителем (динамиком) компьютера и может
быть использован для генерации различных звуков или музыки либо как
генератор случайных чисел. Канал использует режим 3 таймера.
74
Системный генератор
F = 1193180 Гц
импульсов
CLOCK0
OUT На IRQ0
КАНАЛ 0
Лог. GATE0 0
1
CLOCK1
OUT Регенерация
КАНАЛ 1
Лог. GATE1 1 памяти
1
CLOCK
OUT
2 КАНАЛ 2
2
Порт 61h
Динамик
7 6 5 4 3 2 1 0 &
Младший бит этого порта при установке в 1 разрешает работу канала, т.е.
генерацию импульсов для динамика. Дополнительно для управления
динамиком используется бит 1 порта 61h. Если этот бит установлен в 1,
импульсы от канала 2 таймера смогут проходить на динамик.
Системный генератор импульсов (СГИ) независимо от типа и
производительности компьютера IBM вырабатывает импульсы одной и той же
частоты – 1 193 180 Гц.
Таким образом, для включения звука надо выполнить следующие
действия:
• запрограммировать канал 2 таймера на нужную частоту (т.е. загрузить
в регистр счетчика канала значение, равное отношению частоты СГИ и
требуемой частоты звука);
• для включения звука установить в 1 два младших разряда порта 61h.
Поскольку остальные разряда порта 61h используются для других целей,
они должны быть оставлены без изменения.
Для выключения звука надо сбросить два младших разряда порта 61h (не
изменяя опять-таки состояния остальных разрядов).
Для генерации звука без таймера надо сбросить младший бит порта 61h
(запретив тем самым работу канала 2 таймера) и, управляя битом 1 этого
порта, т.е. устанавливая этот бит то в 1, то в 0, формировать импульсы для
динамика. Высота генерируемого звука будет соответствовать периоду
импульсов. Отметим, что этим способом можно генерировать импульсы
любой скважности, что дает больше возможностей для создания различных
звуковых эффектов.
outportb(0x42,kd);
Лабораторная работа 10
CGA имеет 16К байт памяти на плате, начиная с адреса памяти B8000h.
Этого достаточно для отображения одного графического экрана, или для
отображения от четырех до восьми экранов текста в зависимости от числа
символов в строке – 40 или 80.
0110 коричневый
0111 серый
1000 темно-серый
1001 ярко-синий
1010 светло-зеленый
1011 светло-голубой
1100 светло-красный
1101 светло-розовый
1110 желтый
1111 белый
10.4.1.3. Если слова заданы в виде строки символов s типа string, то для
определения ASCII кода k-й буквы строки можно воспользоваться
выражением ord(s[k]).
#include <dos.h>
int86(0x10,&in,&out);
*(uk + i*160+j*2)=kod;
*(uk + i*160+j*2+1)=attr;
1. Первые два слова красным цветом на белом фоне; третье слово синим
высокой интенсивности; четвертое слово зеленое мигающее на красном.
2. Первые три слова синим цветом на красном фоне; второе слово
высокой интенсивности.
3. Второе слово магента на черном фоне; пятое слово мигает; седьмое
слово белым низкой интенсивности.
4. Первые три слова синим на белом фоне; четвертое слово красным
высокой интенсивности; шестое слово зеленым мигающим.
5. Седьмое слово белым черном фоне; пятое слово красным цветом
высокой интенсивности; первые три слова синим цветом мигают.
6. Два слова цвета циан на красном фоне; третье слово мигает; первое
слово коричневым высокой интенсивности.
7. Первые два слова синим высокой интенсивности; третье слово мигает;
четвертое слово зеленое на красном фоне.
8. Первое слово черным на белом фоне; четвертое слово красным на
зеленом фоне мигает; шестое слово коричневым высокой интенсивности.
9. Второе слово розовое высокой интенсивности; третье слово циан на
зеленом фоне; пятое слово мигает.
10. Первые два слова синим низкой интенсивности; третье слово мигает;
четвертое слово красным цветом на белом фоне.
11. Четные слова голубым по розовому; нечетные – красным по черному;
последнее пятое слово мигает.
12. Первое слово черным на белом фоне; четвертое слово зеленое на
красном фоне; остальные – голубым на черном фоне.
Лабораторная работа 11
в качестве этого атрибута следует применять код ASCII 112. Другой способ -
заставить символ, на который указывает курсор, мигать. В этом случае надо
просто добавить 128 к текущему значению атрибута, чтобы символ начал
мигать, и вычесть 128, чтобы прекратить мигание. Третий способ – установить
для символа режим подчеркивания (код ASCII 1). И наконец, в программах,
использующих командную строку, можно рассмотреть применение
специального графического символа, который следует за последним символом
командной строки, такого, как стрелки, выводимые кодами ASCII 17 или 27.
Отметим, что когда программа получает ввод в нескольких режимах, вы
можете помочь идентифицировать текущий режим за счет особого типа
курсора.
номер блока символов, который берется, когда бит 3 равен 0, а биты 3,2 дают
номер блока символов, когда бит 3 байта атрибутов равен 1; для VGA, SVGA
соответственно биты 1,0,4 определяют номер блока, когда бит 3 равен 0, а
биты 3,2,5 – когда бит 3 равен 1. В случае равенства номеров блоков
возможность использования двух наборов символов отсутствует, но можно
задать любой набор. В стандартных настройках BIOS все эти биты равны 0,
поэтому используется только блок 0. Однако ничто не может помешать вам
поместить свои символы в любую нужную вам позицию в любом блоке. Для
этого необходимо выполнить следующие действия:
• записать 6 в порт 3CЕh (адрес многоцелевого регистра графического
контроллера);
• записать 1 в порт 3CFh (Перевод видеосистемы в графический режим);
• записать 2 в порт 3C4h (адрес регистра маски битовой плоскости);
• записать 4 (0100b) в порт 3C5h (разрешить доступ к 2-й битовой
плоскости);
• записать 4 в порт 3C4h (адрес регистра режима использования
видеопамяти);
• записать 6 в порт 3C5h (отмена режима чет/нечет, который сцеплял
битовые плоскости 0–1 и 2–3 в текстовом режиме);
После разрешения записи с учетом номера блока (Blok), ASCII кода
символа (Kod) и числа байт в описании символа изменяется N байт, начиная с
адреса
Adr = A000h:Blok*2000h+kod*32.
После чего необходимо восстановить регистры и перевести видеосистему
в текстовый режим:
• записать 4 в порт 3C4h (адрес регистра режима);
• записать 2 в порт 3C5h (установка режима чет/нечет);
• записать 2 в порт 3C4h (адрес регистра маски битовой плоскости);
• записать 3 (0011b) в порт 3C5h (разрешить доступ к 0 и 1-й битовым
плоскостям);
• записать 6 в порт 3CЕh (адрес многоцелевого регистра);
• записать Eh в порт 3CFh (перевод в текстовый режим).
Содержимое N байт определяется требуемым изображением символа.
На рис. 11.1 приведено рукописное изображение буквы "И" для матрицы
(8×14).
Обратите внимание на то, что сверху, снизу и справа (или слева) от
изображения символа нужно оставить пустые строки для разделения символов
в строке и между строками. Данная буква описывается следующими 14
байтами: 00, 00, 88, 88, 88, 88, 88, 88, 98, AA, 44, 00, 00, 00.
Если вы изменили стандартный набор символов (Blok=0), то можно в
любой момент восстановить его из ПЗУ.
94
. . . . . . . .
. . . . . . . .
■ . . . ■ . . .
■ . . . ■ . . .
■ . . . ■ . . .
■ . . . ■ . . .
■ . . . ■ . . .
■ . . . ■ . . .
■ . . ■ ■ . . .
■ . ■ . ■ . ■ .
. ■ . . . ■ . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
11.4.1.4. Если слова заданы в виде строки символов s типа string, то для
определения ASCII кода k-й буквы строки можно воспользоваться
выражением ord(s[k]).
11.4.1.5. Блок буфера видеоконтроллера можно представить в виде
массива:
block:array[0..32*256] of byte absolute $A000:$0000.
после чего, например, для записи значения 0Eh в порт 3D5h используется
выражение:
outportb(0x3D5,0x0E);
int86x(0x10,&in,&out,&sr).
char ms[14]={0x00,0x00,0x88,0x88,0x88,0x88,0x88,
0x88,0x98,0xAA,0x44,0x00,0x00,0x00};
Лабораторная работа 12
Лабораторная работа 13
для четных строк экрана, а вторая – для нечетных (строки нумеруются начиная
с верха экрана вниз).
видео
RGB
К системной шине
Интерфейс
Блок монитора
Внешний синхрониза-
интерфейс ции (SEQ)
Видеопамять
Цифро-
аналоговый
Графический
преобразова-
контроллер
тель (DAC)
(CRAPH)
Блок
атрибутов
Графический (ATTRIB)
сопроцессор
Внутренняя шина
одной точки были изменены один, два и четыре бита соответственно. Для этих
операций необходимы огромные затраты процессорного времени, поэтому
графическое программное обеспечение, как правило, работает очень медленно.
Тщательное обдумывание часто позволяет сразу установить все биты одного
байта, а не обращаться к одному и тому же байту 4 или 8 раз.
Функция Сh прерывания 10h устанавливает точку. DX содержит строку, а
CX – столбец. Они отсчитываются от 0. Код цвета помещается в AL. Отметим,
что содержимое AX будет разрушено при выполнении прерывания.
В то время как цвет палитры помещается в младшие биты AL, старший
бит также имеет значение. Если он равен 1, то над цветом производится
операция исключающего ИЛИ с текущим цветом. Напомним, что операция
исключающего ИЛИ устанавливает бит только в том случае, если из двух
сравниваемых битов установлен только один. Если оба сравниваемые бита
равны 1 или оба равны 0, то результат будет 0.
На низком уровне мы имеем возможность прямого доступа к
видеобуферу (отображение в память). Сначала вы должны вычислить
смещение точки а – внутри буфера и б – внутри байта, содержащего биты,
относящиеся к данной точке. После этого битовые операции обеспечат
соответствующую установку.
В режимах Dh, Eh и 10h память разбита на 4 битовые плоскости. Каждая
плоскость организована таким же образом, как для черно-белого режима
высокого разрешения цветного адаптера, когда байт данных посылается в
определенный адрес видеобуфера, каждый бит соответствует горизонтальному
сегменту линии, а бит 7 – самой левой точке. Выводятся четыре такие битовые
плоскости, относящиеся к одним и тем же адресам в видеобуфере. Это
приводит к тому, что каждая точка описывается четырьмя битами (давая 16
цветов), причем каждый бит находится в отдельном байте отдельной битовой
плоскости.
Но как вы можете записать 4 различных байта данных, расположенных по
одному и тому же адресу? Ответ на этот вопрос состоит в том, что вы не
посылаете последовательно четыре байта по этому адресу. Вместо этого один
из трех режимов записи позволяет изменить все 4 байта на основании одного
байта данных, полученного от процессора. Влияние данных, посланных
процессором, зависит от установки нескольких регистров, включающих два
регистра маски, которые определяют, на какие биты и в каких битовых
плоскостях будут изменяться биты. Для понимания этих регистров мы должны
сначала разобраться с четырьмя регистрами задвижки (latch register). Они
содержат данные для четырех битовых плоскостей в той позиции, к которой
было последнее обращение. (Заметим, что термин "битовая плоскость"
используется как для целой области видеобуфера, так и для и однобайтового
буфера, временно хранящегося в регистре задвижки). Когда процессор
111
выражение:
outportb(0x3C0,0x3d);
Лабораторная работа 14
Line_m Inc_x=sign(D_X)
Inc_y=sign(D_Y)
X_err=0 Y_err=0
D_X=EX-BX
D_Y=EY-BY D_X=abs(D_X)
D_Y=abs(D_Y)
да нет
D_X>D_Y
dist=D_X dist=D_Y
t=0, dist
return
Put_pix(BX,
BY, color)
X_err=X_err+D_X
Y_err=Y_err+D_Y
да X_err=X_err-dist
X_err>dist BX=BX+inc_X
нет
да
Y_err=Y_err-dist
Y_err>dist
BY=BY+inc_Y
нет
/* вычерчивание прямоугольника */
void box(startx,starty,endx,endy,color_code)
int startx,starty,endx,endy,color_code;
{
line(startx,starty,endx,starty,color_code);
line(startx,starty,startx,endy,color_code);
line(startx,endy,endx,endy,color_code);
line(endx,starty,endx,endy,color_code);
}
Для того, чтобы закрасить прямоугольник, требуется выполнить запись в
каждую точку растра внутри прямоугольника. При этом необходимо в цикле
рисовать заданным цветом ряд горизонтальных линий, смещенных на единицу
по координате y – функция bar_m().
Тщательное продумывание позволяет исключить излишнюю
медлительность, свойственную многим программам заполнения областей для
графического экрана. Когда заполнение основано на простых вычислениях,
которые действуют по очереди для каждой точки, требуется расходующие
много времени битовые операции. Более экономичный код может определять,
все ли битовые позиции определенного байта видеобуфера должны иметь один
и тот же цвет, и когда это условие выполняется, этому байту присваивается
заранее заготовленное значение, которое устанавливает все точки в
правильный цвет. При этом нет необходимости повторять операции над одним
и тем же байтом, каждый раз устанавливая биты только для одной из точек,
информацию о которой содержит данный байт.
При заполнении прямоугольника линиями только первый и последний
120
байт каждой строки может быть неполным (если BX или EX не кратен 8). При
затушевывании горизонтальными линиями нет смысла использовать
процедуру line_m(), реализующую алгоритм Брезенхейма, необходимо просто
определять адрес байта в видеопамяти, который соответствует в данный
момент 8 выводимым точкам с начальными координатами X и Y, причем X
кратен 8: adr=A000:0000h + X/8 +Y*80.
В работе 11 объяснено, как создать описание символа в виде матрицы 8×8
точек, имеющего требуемый вам вид. Хотя такие символы могут выводиться
только в стандартные символьные позиции, их использование может
существенно облегчить заполнение графиков. Образец, высвечивающий все
8×8 точек можно вывести в интервале несколько строк и столбцов, заполняя
область намного быстрее, чем это достигается при поточечной зарисовке.
При затушевывании прямоугольника в центральной части желательно
использовать символы псевдографики с кодами ASCII 219, 220, 221, 222, 223,
которые заполняют все, знакоместо (219), нижнюю половину (220),
левую(221), правую (222) и верхнюю (223). При изображении прямоугольника
тоже нет смысла применять алгоритм Брезенхейма, так как он состоит из
горизонтальных и вертикальных отрезков. Изображение горизонтальных
отрезков выполняется аналогично рассмотренному выше способу
затушевывания горизонтальными линиями, а изображение вертикальных
отрезков сводится к выводу в цикле одного байта с заданной частной (при
текущей линии в 1 пиксель маска содержит одну 1) и приращение адреса на 80
– переход на следующую строку. Модификация изображения наклонной
линии.
При работе алгоритма Брезенхейма в случае D_X > D_Y в каждой строке
выводится несколько точек. Если перед блоком 9 в алгоритме анализировать
значение BX при неизменном BY и дописывать 1 в битовую маску. Тогда при
использовании разработанной в лабораторной работе процедуры вывода байта
с заданной маской обращение к ней выполняется только в случае кратности 8
значения BX (переход на следующий адрес видеопамяти) или изменения BY
(переход на следующую строку). В случае если D_Y > D_X и толщина линии
составляет 2, 3, и т.д. пикселя за одно обращение к put_pix() можно выводить
соответствующее число точек (если они относятся к одному адресу
видеопамяти).
где: Xn1, Yn1, Xk1, Yk1 – координаты верхнего левого (индекс n ), и правого
(индекс k) угла прямоугольника; L1 – толщина линии в прямоугольнике; color1
– цвет; Xn2, Yn2, Xk2, Yk2, color2 – соответствующие параметры
затушевывания. Xn3, Yn3, Xk3, Yk3, L3, color3 – координаты, толщина и цвет
наклонной линии.
Лабораторная работа 15
после чего, например, для записи значения 3Dh в порт 3C0h используется
выражение:
outportb(0x3C0,0x3D);
Для чтения из порта 3DAh используется выражение:
data=intportb(0x3DA),где data- переменная типа char;
ЛИТЕРАТУРА
АРХІТЕКТУРА КОМП’ЮТЕРІВ
Лабораторний практикум
В авторській редакції
Видавництво Курсор. Україна, 61057, м. Харків, пр. Театральний 11/13, (057) 706-31-73
Свідоцтво про внесення до Державного реєстру суб’єктів видавничої справи
серія №21 від 24.03.2000 р.