Заметки за 2020 год

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

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

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

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

  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 текстура

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

 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             ; Возврат

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

XOR текстура