Создание текстуры командой XOR

На ассемблере в графическом режиме VGA

Как сгенерировать интересную текстуру при помощи всего одной команды?! Ну хорошо, команд будет немного больше.

Однако, гораздо меньше чем в предыдущей заметке по ассемблеру Создание эффекта огня на ассемблере.

В качестве каркаса я использовал тот-же код, что и раньше. Если коротко, что делает программа:

  1. Устанавливает графический режим VGA с разрешением 320×200 точек и 256 цветов.
  2. Записывает палитру-градиент от чёрного к синему.
  3. Отрисовывает текстуру на весь экран.
  4. Ждёт нажатия клавиши.

Собственно шаг номер три, а именно процедура 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

А «специально» подобранная палитра создаёт вырвиглазный эффект!

XOR текстура

Ниже полный листинг программы с комментариями.

 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
org 100h

;------------------------------------------------------------------------------
; XOR.ASM

mov ax,0013h    ; Выбираем режим 320x200 256 цветов
int 10h         ; Видеосервис: Установка видеорежима

push 0A000h     ; Отправляем в стэк адрес сегмента видеопамяти
pop es          ; Извлекаем адрес сегмента видеопамяти в ES
xor di,di       ; Обнуляем смещение от начала сегмента видеопамяти

call palset     ; Записываем цвета палитры
call drawtex    ; Вызываем генерацию текстуры

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 0,0,%-1      ; от 0,0,0 до 0,0,63
end repeat

repeat 64       ; Синий -> 
db 0,%-1,63     ; от 0,0,63 до 0,63,63
end repeat

repeat 64       ; Чёрный -> Синий
db 0,0,%-1      ; от 0,0,0 до 0,0,63
end repeat

repeat 64       ; Синий -> 
db 0,%-1,63     ; от 0,0,63 до 0,63,63
end repeat

;------------------------------------------------------------------------------
; Функция генерации текстуры

drawtex:

xor di, di      ; Обнуляем смещение

mov dx, 200     ; Цикл для 200 линий
vertloop:

mov cx, 320     ; Цикл для 320 точек
horloop:

mov ax, cx      ; Копируем содержимое CX в аккумулятор
xor ax, dx      ; И ксорим с DX, здесь вся «магия»!
stosb           ; Записываем содержимое регистра AL в байт по адресу ES:DI

loop horloop    ; Повторяем для каждой точки строки
    
dec dx
jnz vertloop    ; Повторяем для каждой линии

ret             ; Возврат

Ну, красота же!

XOR текстура