Ассемблер под Windows №23

OpenGL и структура команд процессора Intel №2


Доброго времени суток, уважаемые подписчики.
Внимание, если в вашем почтовом клиенте не видны рисунки, то откройте страницу из броузера


Сегодня мы продолжим разбираться в структуре команд процессора. Я считаю, следует привести один пример к прошлому уроку:
Такую структуру имеют команды условного перехода и условной пересылки данных. "Условие" может принимать следующие значения:
0000o
0001no
0010c/b/nae
0011nc/nb/ae
0100e/z
0101ne/nz
0110be/na
0111nbe/a
1000s
1001ns
1010p/pe
1011np/po
1100l/nge
1101nl/ge
1110le/ng
1111lne/g
Этот тип команд, как и другие похожие (рассмотренные на прошлом уроке), являются достаточно простыми для раскодировки (простая проверка статической части). Для понятия следующих типов команд, нам нужно понять структуру байта следующего за статической частью команды (так называемый ModR/M байт). Он содержит три секции, R/M (register/memory usage, биты 2-0), R/O (register/opcode, биты 5-3) и MOD (биты 7-6). Начнём с конца, Mod содержит тип информации байта ModR/M, он принимает следующие значения:
00используется адрес без смещения(например [esi])
01адресация с 8 байтным смещением(например [esi+x], где -128<x<127)
10используется адресация с полным смещением(например [esi+x])
11R/M содержит код регистра
Поле R/O содержит либо дополнительные три бита статической команды, либо код регистра.
Поле R/M может содержать следующие значения:
код16 бит32 бита
000[bx+si][eax]
001[bx+di][ecx]
010[bp+si][edx]
011[bp+di][ebx]
100[si]используется SIB
101[di][ebp]
110[bp][esi]
111[bx][edi]
Байт SIB, если он нужен, находится сразу за ModR/M, он является расширением ModR/M и появляется только при 32-битной адресации. Так как он не представляет никакого интереса с точки зрения идентификации команды, его мы рассмотрим позже. Как вы могли догадаться, я только что объяснил вам строение очередного типа команды (один или больше байт команды и описание адресации). Всё это хорошо и легко понятно, но, к сожалению, это не всё. Следующий тип команд, на мой взгляд, самый странный. Вначале приведу пару примеров:
Командакод
adc eax,583 D0 05
add ecx,583 C1 05
and edx,583 E2 05
cmp ebx,583 FB 05
or  esi,583 CE 05
sbb edi,583 DF 05
sub ebp,583 ED 05
xor esp,583 F4 05
Посмотрите, выходит у команд одинаковый статический код?! Как же тогда компьютер определяет что ему делать с регистром? В этом случае биты 5-3 байта ModR/M (секция R/O). Это означает, что даже при одинаковой части "кода" статический код может отличаться:
В принципе остальные команды отличаются лишь длинной статического кода, поэтому я думаю следует приступить к следующему шагу, разработке алгоритма декодировки команд.. Этим и займёмся в следующем уроке.


А теперь вернёмся к проекту игры. Следующим шагом после создания окна должно быть создание фигур в окне. Так как мы будем работать с числами с плавающей запятой, то нам может пригодиться следующий файл констант:
_1   equ 03f800000h
_2   equ 040000000h
_3   equ 040400000h
_4   equ 040800000h
_5   equ 040a00000h
_6   equ 040c00000h
_7   equ 040e00000h
_8   equ 041000000h
_9   equ 041100000h
_10  equ 041200000h
_11  equ 041300000h
_12  equ 041400000h
_m1  equ 0bf800000h
_m2  equ 0c0000000h
_m3  equ 0c0400000h
_m4  equ 0c0800000h
_m5  equ 0c0a00000h
_m6  equ 0c0c00000h
_m7  equ 0c0e00000h
_m8  equ 0c1000000h
_m9  equ 0c1100000h
_m10 equ 0c1200000h
_m11 equ 0c1300000h
_m12 equ 0c1400000h
То есть если мы хотим передать функции OpenGL определённый числовой параметр, то, так как в большинстве случаев параметр должен быть числом с плавающей запятой, мы будем должны знать заранее, какое значение имеет определённое число... Но вернёмся к выводу объектов на экран OpenGL. Создание объекта в OpenGL происходит следующим образом:
- вызываем функцию glBegin, передавая её код того, что мы хотим нарисовать
- с помощью функций glVertex**(v) задаём вершины объекта
- для завершения рисования объекта вызываем glEnd
Функция glBegin поддерживает следующие параметры:
GL_POINTSРисует точки
GL_LINESЛинии
GL_LINE_STRIPРисует несколько соединённых линий
GL_LINE_LOOPРисует несколько соединённых линий, последняя точка соединяется с первой
GL_TRIANGLESРисует треугольники
GL_TRIANGLES_STRIPРисует несколько треугольников так, что каждые два имеют одну общую сторону
GL_TRIANGLE_FANРисует несколько треугольников с общей вершиной
GL_QUADSРисует квадраты
GL_QUAD_STRIPРисует несколько квадратов так, что каждые два имеют общую сторону
GL_POLYGONРисует полигон, то же что и GL_LINE_LOOP, только заполнен изнутри
Функция, а вернее функции, glVertex**(v) имеет достаточно интересный синтаксис и её можно записать как glVertexXTV, где "X" может принимать значения от 2 до 4, "T" может принимать несколько буквенных значений, а "V" всегда имеет значение 'v', но её присутствие необязательно. Что же всё это значит?! Дело в том, что для облегчения использования OpenGL работает с множеством типов данных, тип данных задаётся переменной "T" и может принимать следующие значение:
ddoubleqword*
ffloatdword*
iintdword
sshortbyte

* - числа с плавающей запятой
"Х" - определяет кол-во указанных осей, а "V" указывает, передаются переменные или лишь указатель на переменные.

Наиболее разумно вставлять функции создания объектов в нашу процедуру DrawGLWindow (смотри прошлый урок). Нарисуем обычный треугольник:
DrawGLScene proc
 push esi
 null esi
 run glClear, GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT
 run glLoadIdentity
 run glTranslatef, esi, esi, _m5
 run glBegin, GL_TRIANGLES
 run glVertex3f, _m1, _m1, esi
 run glVertex3f, esi, _1,  esi
 run glVertex3f, _1,  _m1, esi
 run glEnd
 run glLoadIdentity
 pop esi
 ret
DrawGLScene endp
Чтоб всё это работало правильно следует добавить обработку сообщения WM_SIZE в нашей процедуре окна, то есть следует дописать следующее:
 ...
 mov eax,[ebp+0ch]
 cmp eax,WM_SIZE
 je size_proc

 cmp eax,WM_DESTROY
 ...
 jmp short Pass_Message
size_proc:
 mov eax,[ebp+14h]
 mov ecx,eax
 cwde
 shr ecx,16
 mov width_,eax
 mov height_,ecx
 run ReSizeGLScene
key_proc:
 ...
Ассемблерный код можно скачать здесь, а откомпилированную программу здесь.


На сегодня это всё. Если есть какие вопросы, пишите. Пишите на Dark_Lord@RusFAQ.ru или Dark_Lord@land.ru.
Или свяжитесь со мной по ICQ, мой номер 126222874!

Сайт управляется системой uCoz