Заметки за 2020 год
Создание текстуры командой XOR
Как сгенерировать интересную текстуру при помощи всего одной команды?! Ну хорошо, команд будет немного больше.
Однако, гораздо меньше чем в предыдущей заметке по ассемблеру Создание эффекта огня на ассемблере.
В качестве каркаса я использовал тот-же код, что и раньше. Если коротко, что делает программа:
- Устанавливает графический режим VGA с разрешением 320×200 точек и 256 цветов.
- Записывает палитру-градиент от чёрного к синему.
- Отрисовывает текстуру на весь экран.
- Ждёт нажатия клавиши.
Собственно шаг номер три, а именно процедура drawtex (79-99 строки), содержит в себе два цикла.
Первый цикл для каждой из 200 линий экрана хранит свой счётчик в регистре DX. Второй, для каждой из 320 точек линии, хранит свой счётчик в регистре CX. В сердце этих циклов находится команда XOR.
Команда XOR выполняет операцию исключающего ИЛИ между всеми битами двух операндов. Если сравниваемые биты равны, то результат будет 0. И если сравниваемые биты отличаются, то результат будет 1.
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0
В качестве операндов используются счётчики циклов из регистров DX и CX, по сути координаты X и Y. А результат используется как индекс палитры-градиента, и записывается в экранную область по своим координатам.
Например, вот результат ксорок нескольких точек:
CX XOR DX = Color Index
-----------------------
91 XOR 61 = 102
92 XOR 61 = 97
91 XOR 62 = 101
92 XOR 62 = 98
А «специально» подобранная палитра создаёт вырвиглазный эффект!

Ниже полный листинг программы с комментариями.
1org 100h
2
3;------------------------------------------------------------------------------
4; XOR.ASM
5
6mov ax,0013h ; Выбираем режим 320x200 256 цветов
7int 10h ; Видеосервис: Установка видеорежима
8
9push 0A000h ; Отправляем в стэк адрес сегмента видеопамяти
10pop es ; Извлекаем адрес сегмента видеопамяти в ES
11xor di,di ; Обнуляем смещение от начала сегмента видеопамяти
12
13call palset ; Записываем цвета палитры
14call drawtex ; Вызываем генерацию текстуры
15
16xor ah,ah ; Выбираем режим ожидания ввода AH = 00h
17int 16h ; Сервис клавиатуры: пауза до нажатия на клавишу
18
19mov ax,0003h ; Выбираем текстовый режим 80x25 16 цветов
20int 10h ; Видеосервис: Установка видеорежима
21
22int 20h ; Выходим в DOS
23
24;------------------------------------------------------------------------------
25; Функция записи цветов в таблицу палитры
26
27palset:
28
29mov dx,03c8h ; В DX будет храниться адрес порта ЦАП для управления палитрой
30xor ax,ax ; Обнуляем аккумулятор
31out dx,al ; Записываем в порт 03c8h индекс 0-го элемента палитры
32inc dx ; Увеличивает адрес порта на 1
33
34mov cx,256 ; Устанавливаем счётчик цикла по всем 256 цветам палитры
35mov bx,pal ; В BX будет адрес начала сгенерированных данных палитры
36
37ps_l1:
38
39mov al,[bx] ; Берём содержимое байта из BX
40out dx,al ; Записываем его в порт 03c9h это будет R
41inc bx ; Смещаем указатель адреса данных палитры на 1
42
43mov al,[bx] ; Берём содержимое байта из BX
44out dx,al ; Записываем его в порт 03c9h это будет G
45inc bx ; Смещаем указатель адреса данных палитры на 1
46
47mov al,[bx] ; Берём содержимое байта из BX
48out dx,al ; Записываем его в порт 03c9h это будет B
49inc bx ; Смещаем указатель адреса данных палитры на 1
50
51loop ps_l1 ; Повторяем пока не запишутся все цвета
52
53ret ; Возврат
54
55;------------------------------------------------------------------------------
56; Палитра
57
58pal:
59
60repeat 64 ; Чёрный -> Синий
61db 0,0,%-1 ; от 0,0,0 до 0,0,63
62end repeat
63
64repeat 64 ; Синий ->
65db 0,%-1,63 ; от 0,0,63 до 0,63,63
66end repeat
67
68repeat 64 ; Чёрный -> Синий
69db 0,0,%-1 ; от 0,0,0 до 0,0,63
70end repeat
71
72repeat 64 ; Синий ->
73db 0,%-1,63 ; от 0,0,63 до 0,63,63
74end repeat
75
76;------------------------------------------------------------------------------
77; Функция генерации текстуры
78
79drawtex:
80
81xor di, di ; Обнуляем смещение
82
83mov dx, 200 ; Цикл для 200 линий
84vertloop:
85
86mov cx, 320 ; Цикл для 320 точек
87horloop:
88
89mov ax, cx ; Копируем содержимое CX в аккумулятор
90xor ax, dx ; И ксорим с DX, здесь вся «магия»!
91stosb ; Записываем содержимое регистра AL в байт по адресу ES:DI
92
93loop horloop ; Повторяем для каждой точки строки
94
95dec dx
96jnz vertloop ; Повторяем для каждой линии
97
98ret ; ВозвратНу, красота же!
