1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
| org 100h
;------------------------------------------------------------------------------
; FIRE.ASM
mov ax,0013h ; Выбираем режим 320x200 256 цветов
int 10h ; Видеосервис: Установка видеорежима
push 0A000h ; Отправляем в стэк адрес сегмента видеопамяти
pop es ; Извлекаем адрес сегмента видеопамяти в ES
xor di,di ; Обнуляем смещение от начала сегмента видеопамяти
call palset ; Записываем цвета палитры
call dpal ; Вызываем отрисовку палитры
mainloop: ; Метка главного цикла
call dline ; Вызываем отрисовку линии точек случайных цветов внизу экрана
call updscr ; Вызываем вычисление цвета точек на экране
mov ah,1 ; Выбираем режим ожидания ввода AH = 01h
int 16h ; Сервис клавиатуры: проверяем нажатие на клавишу
jz mainloop ; Если нажатия не было возвращаемся на метку mainloop
xor ah,ah ; Выбираем режим ожидания ввода AH = 00h
int 16h ; Сервис клавиатуры: пауза до нажатия на клавишу
mov ax,0003h ; Выбираем текстовый режим 80x25 16 цветов
int 10h ; Видеосервис: Установка видеорежима
int 20h ; Выходим в DOS
;------------------------------------------------------------------------------
; Функция записи цветов в таблицу палитры
palset:
mov dx,03c8h ; В DX будет храниться адрес порта ЦАП для управления палитрой
xor ax,ax ; Обнуляем аккумулятор
out dx,al ; Записываем в порт 03c8h индекс 0-го элемента палитры
inc dx ; Увеличивает адрес порта на 1
mov cx,256 ; Устанавливаем счётчик цикла по всем 256 цветам палитры
mov bx,pal ; В BX будет адрес начала сгенерированных данных палитры
ps_l1:
mov al,[bx] ; Берём содержимое байта из BX
out dx,al ; Записываем его в порт 03c9h это будет R
inc bx ; Смещаем указатель адреса данных палитры на 1
mov al,[bx] ; Берём содержимое байта из BX
out dx,al ; Записываем его в порт 03c9h это будет G
inc bx ; Смещаем указатель адреса данных палитры на 1
mov al,[bx] ; Берём содержимое байта из BX
out dx,al ; Записываем его в порт 03c9h это будет B
inc bx ; Смещаем указатель адреса данных палитры на 1
loop ps_l1 ; Повторяем пока не запишутся все цвета
ret ; Возврат
;------------------------------------------------------------------------------
; Палитра
pal:
repeat 64 ; Чёрный -> Красный
db %-1,0,0 ; от 0,0,0 до 63,0,0
end repeat
repeat 64 ; Красный -> Жёлтый
db 63,%-1,0 ; от 63,0,0 до 63,63,0
end repeat
repeat 64 ; Жёлтый -> Белый
db 63,63,%-1 ; от 63,63,0 до 63,63,63
end repeat
repeat 64 ; Белый
db 63,63,63 ; 63,63,63
end repeat
;------------------------------------------------------------------------------
; Функция отрисовки палитры на экране
dpal:
xor ax,ax ; Обнуляем текущий индекс цвета палитры
xor dx,dx ; Обнуляем индекс цвета палитры для строки
mov cx,8 ; Цикл для 8 строк
dp_l4:
push cx ; Отправляем значение счётчика dp_l4 в стэк
mov cx,25 ; Цикл для 25 линий
dp_l3:
push cx ; Отправляем значение счётчика dp_l3 в стэк
mov cx, 32 ; Цикл для 32 цветов
dp_l2:
push cx ; Отправляем значение счётчика dp_l2 в стэк
mov cx,10 ; Цикл для 10 точек
dp_l1:
stosb ; Записываем байт в память
loop dp_l1 ; Повторяем 10 раз
pop cx ; Восстанавливаем значение счётчика dp_l2 из стэка
inc al ; Увеличиваем индекс цвета на один
loop dp_l2 ; Повторяем 32 раза
pop cx ; Восстанавливаем значение счётчика dp_l3 из стэка
mov ax,dx ; Устанавливаем текущее значение индекса цвета для строки
loop dp_l3 ; Повторяем 25 раз
pop cx ; Восстанавливаем значение счётчика dp_l4 из стэка
add al,32 ; Увеличиваем текущий индекс цвета на 32
mov dx,ax ; Сохраняем начальный индекс цвета палитры для строки
loop dp_l4 ; Повторяем 8 раз
ret ; Возврат
;------------------------------------------------------------------------------
; Функция генерации случайного числа
rand:
mov ax,[seed] ; Сохраняем в аккумулятор начальное значение семячка
mov dx,8405h ; Заносим в DX «магическое» число
mul dx ; Умножаем начальное значение в AX на «магическое» число в DX
mov [seed],ax ; Сохраняем младшие 16 бит результата умножения как новое семячко
mov ax,dx ; Возвращаем старшие 16 бит результата от умножения
ret ; Возврат
seed: dw 3749h ; Начальное значение
;------------------------------------------------------------------------------
; Функция отрисовки полоски точек случайных цветов
dline:
mov di,320*199 ; Заносим в смещение первую точку последнего ряда экрана
mov cx,320 ; Цикл для 320 точек
randpix:
call rand ; Получаем случайное число в AX
stosb ; Записываем содержимое регистра AL в байт по адресу ES:DI
loop randpix ; Повторяем для каждой точки строки
ret ; Возврат
;------------------------------------------------------------------------------
; Функция вычисления цвета точек на экране
updscr:
mov cx,320*199 ; Цикл для 320×199 точек, это весь экран кроме последнего ряда
xor di,di ; Обнуляем смещение
updpix:
push di ; Запоминаем текущее смещение
xor ax,ax ; Обнуляем аккумулятор
xor dx,dx ; Обнуляем регистр данных
add di,320 ; Увеличиваем смещение на строку вниз
dec di ; и уменьшаем на пиксель влево, ниже и левее
mov dl,[es:di] ; Сохраняем байт в младшую часть регистра DL
add ax,dx ; Складываем с аккумулятором
inc di ; Увеличиваем смещение на пиксель вправо, точно под точкой
mov dl,[es:di] ; Сохраняем байт в младшую часть регистра DL
add ax,dx ; Складываем с аккумулятором
inc di ; Увеличиваем смещение на пиксель вправо, ниже и правее
mov dl,[es:di] ; Сохраняем байт в младшую часть регистра DL
add ax,dx ; Складываем с аккумулятором
add di,319 ; Увеличиваем смещение на строку вниз и на пиксель влево
mov dl,[es:di] ; Сохраняем байт в младшую часть регистра DL
add ax,dx ; Складываем с аккумулятором
sar ax,2 ; Арифметический сдвиг вправо, знаковое деление на четыре
jz next
dec al ; Дополнительное уменьшение яркости
next:
pop di ; Восстанавливаем текущее смещение
stosb
loop updpix
ret ; Возврат
|