Смекни!
smekni.com

Графика на языке Assembler (стр. 1 из 2)

Федеральное агентство по образованию

ГОУ ВПО

Уфимский государственный авиационный технический университет

Курсовая работа

по дисциплине «Микропрограммирование»

«Графика на языке Assembler»

Выполнил:

студент гр. ПО-228

Елизарьев Д.И.

Уфа

2008

1. Постановка задачи

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

Программа реализована на языке “Assembler”. Для вывода графики на экран используется прямое обращение к видеобуферу. Для достижения плавности прорисовки изображения применяется синхронизация с вертикальной развёрткой монитора.

Повороты вокруг осей производятся по следующим формулам:

· Вокруг оси X:

· Вокруг оси Y:

· Вокруг оси Z:

Для рисования линии используется алгоритм Брезенхэма.

Значения синуса и косинуса вычисляются при помощи таблицы синусов для углов от 0 до 90 градусов.

2. Текст программы.

DATASSEGMENT

X DW 0 ;Промежуточнаякоордината X

Y DW 0 ;Промежуточная координата Y

Z DW 0 ;Промежуточная координата Z

ANX DW 0 ;Текущий угол поворота вокруг оси X

ANY DW 0 ;Текущий угол поворота вокруг оси Y

ANZ DW 0 ;Текущий угол поворота вокруг оси Z

DeltaX DW 2 ;Приращение угла поворота вокруг оси X

DeltaY DW 2 ;Приращение угла поворота вокруг оси Y

DeltaZ DW 2 ;Приращение угла поворота вокруг оси Z

X2D DW 0 ;Проекция трехмерной точки на плоскость

Y2D DW 0 ;

X1 DW 0 ;Координаты

Y1 DW 0 ;начала и

X2 DW 0 ;конца

Y2 DW 0 ;линии

DelX DW 0 ;Промежуточные

DelY DW 0 ;переменные,

LenX DW 0 ;используемые

LenY DW 0 ;в процедуре

Leng DW 0 ;рисования

D DW 0 ;линии

COLOR DB 10 ;Цвет фигуры

FULLCIRCLE DW 360 ;Константа = 360 градусов

POINTS DW 8 ;Количество вершин

WID DW 320 ;Ширина экрана

;Таблица синусов углов от 0 до 90 градусов.

;Каждое значение синуса умножено на 512

SINES DW 0, 9, 18, 27, 36, 45

DW 54, 62, 71, 80, 89

DW 98, 106, 115, 124, 133

DW 141, 150, 158, 167, 175

DW 183, 192, 200, 208, 216

DW 224, 232, 240, 248, 256

DW 264, 271, 279, 286, 294

DW 301, 308, 315, 322, 329

DW 336, 343, 349, 356, 362

DW 368, 374, 380, 386, 392

DW 398, 403, 409, 414, 419

DW 424, 429, 434, 439, 443

DW 448, 452, 456, 460, 464

DW 468, 471, 475, 478, 481

DW 484, 487, 490, 492, 495

DW 497, 499, 501, 503, 504

DW 506, 507, 508, 509, 510

DW 511, 511, 512, 512, 512

;Координаты вершин куба

CUBE DW 20, 20, 20

DW 20, 20, -20

DW 20, -20, -20

DW 20, -20, 20

DW -20, -20, 20

DW -20, 20, 20

DW -20, 20, -20

DW -20, -20, -20

DATAS ENDS

CODES SEGMENT

ASSUME DS:DATAS, CS:CODES

FIND_SIN PROC ;Нахождение синуса угла от 0 до 360 градусов

push ax

push cx

sub cx, cx

cmp ax, 181

jb SIN_POS

mov cx, 8000h

sub ax, 180

SIN_POS:

cmp ax, 91

jb GET_SIN

neg ax

add ax, 180

GET_SIN:

mov bx, ax

shl bx, 1

mov bx, sines[bx]

cmp cx, 8000h

jne NE1

neg bx

NE1:

pop cx

pop ax

ret

FIND_SIN ENDP

FIND_COS PROC ;Нахождение косинуса угла от 0 до 360 градусов

push ax

push cx

sub cx, cx

cmp ax, 91 ;если угол 90 и меньше,

jb COS_POS ;то знак положительный

cmp ax, 269 ;если угол 270 и больше, то знак "плюс"

jg CP

mov cx, 8000h ;иначе ставим флаг в CX, что знак "минус"

sub ax, 90 ;делаем поправку на 90

cmp ax, 91

jb GET_COS ;если < 91

neg ax ;иначеугол = 180 - угол

add ax, 180

jmp GET_COS

CP:

sub ax, 270 ;угол = 270 - угол

jmp GET_COS

COS_POS:

neg ax

add ax, 90

cmp ax, 91

jb GET_COS

neg ax

add ax, 360

GET_COS: ;достаём значение косинуса из таблицы синусов

mov bx, ax

shl bx, 1

mov bx, sines[bx]

cmp cx, 8000h

jne NE2 ;если знак "минус",

neg bx ;то меняем знак

NE2:

pop cx

pop ax

ret

ENDP FIND_COS

PUTPIXEL PROC ;Рисование точки в X2D, Y2D, цветом COLOR

push ax

push di

mov ax, 100 ;Высота экрана/2

sub ax, Y2D

push dx

mul WID ;Index = Y * WIDTH

pop dx

add ax, X2D ;Index + X

add ax, 160

mov di, ax

mov al, COLOR

mov byte ptr ES:[di], al ;рисуемточку

pop di

pop ax

ret

ENDP PUTPIXEL

PROJECTPROC ;Проецирование трёхмерной точки на плоскость

push ax

mov ax, X

mov X2D, ax

mov ax, Y

mov Y2D, ax

pop ax

ret

ENDP PROJECT

ROTX PROC ;Поворот точки вокруг оси X

push cx

push ax

push bx

push dx

mov ax, ANX

CALL FIND_COS ;

mov ax, bx ;

imul Y ;

mov cx, ax ;

mov ax, ANX ;

CALL FIND_SIN ;YNEW = Y*COS(ANX) - Z*SIN(ANX)

mov ax, bx ;

imul Z ;

neg ax ;

add ax, cx ;

sar ax, 9

mov cx, Y

mov Y, ax

mov ax, ANX ;

CALL FIND_SIN ;

mov ax, bx ;

imul cx

mov cx, ax ;

mov ax, ANX ;ZNEW = Y*SIN(ANX) + Z*COS(ANX)

CALL FIND_COS ;

mov ax, bx ;

imul Z ;

add ax, cx ;

sar ax, 9

mov Z, ax

pop dx

pop bx

pop ax

pop cx

ret

ENDP ROTX

ROTY PROC ;Поворот точки вокруг оси Y

push cx

push ax

push bx

push dx

mov ax, ANY

CALL FIND_COS ;

mov ax, bx ;

imul X ;

mov cx, ax ;

mov ax, ANY ;

CALL FIND_SIN ;XNEW = X*COS(ANY) - Z*SIN(ANY)

mov ax, bx ;

imul Z ;

neg ax ;

add ax, cx ;

sar ax, 9

mov cx, X

mov X, ax

mov ax, ANY ;

CALL FIND_SIN ;

mov ax, bx ;

imul cx ;

mov cx, ax ;

mov ax, ANY ;ZNEW = X*SIN(ANY) + Z*COS(ANY)

CALL FIND_COS ;

mov ax, bx ;

imul Z ;

add ax, cx ;

sar ax, 9

mov Z, ax

pop dx

pop bx

pop ax

pop cx

ret

ENDP ROTY

ROTZ PROC ;Поворот точки вокруг оси Z

push cx

push ax

push bx

push dx

mov ax, ANZ

CALL FIND_COS ;

mov ax, bx ;

imul X ;

mov cx, ax ;

mov ax, ANZ ;

CALL FIND_SIN ;XNEW = X * COS(ANZ) - Y * SIN(ANZ)

mov ax, bx ;

imul Y ;

neg ax ;

add ax, cx ;

sar ax, 9

mov cx, X

mov X, ax

mov ax, ANZ ;

CALL FIND_SIN ;

mov ax, bx ;

imul cx ;

mov cx, ax ;

mov ax, ANZ ;YNEW = X * SIN(ANZ) + Y * COS(ANZ)

CALL FIND_COS ;

mov ax, bx ;

imul Y ;

add ax, cx ;

sar ax, 9

mov Y, ax

pop dx

pop bx

pop ax

pop cx

ret

ENDP ROTZ

WAITVRT PROC ;Ждётвертикальнуюразвёрткумонитора.

mov dx,3dah ;3DAh - Номер порта экрана

Vrt:

in al,dx

test al,8

jnz Vrt ;Ждать пока развёртка начнётся

NoVrt:

in al,dx

test al,8

jz NoVrt ;Ждать, пока развёртка закончится

ret

ENDP WAITVRT

;Процедура рисования куба.

;Здесь последовательно вычисляются координаты двух соседних ;вершин, и проводится линия между ними.

;Всего 16 линий.

DRAWCUBE PROC

push cx

push ax

push bx

push dx

mov cx, POINTS

mov si, 0

DRC:

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

add si, 6

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

add si, 6

CALL LINE

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

add si, 6

CALL LINE

mov si, 12

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

CALL LINE

mov si, 24

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

mov si, 0

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

mov si, 30

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

CALL LINE

mov si, 18

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

CALL LINE

mov si, 6

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

mov si, 36

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

CALL LINE

mov si, 42

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X1, ax

mov Y1, bx

mov si, 24

mov ax, CUBE[si]

mov bx, CUBE[si+2]

mov dx, CUBE[si+4]

mov X, ax

mov Y, bx

mov Z, dx

CALL ROTX

CALL ROTY

CALL ROTZ

CALL PROJECT

mov ax, X2D

mov bx, Y2D

mov X2, ax

mov Y2, bx

CALL LINE

pop dx

pop bx

pop ax

pop cx

ret

ENDP DRAWCUBE

;Алгоритм Брезенхэма для линии.

;Суть алгоритма заключается в том, что мы на каждом шаге ;увеличиваем координату Xна единицу, и прибавляем к так ;называемой «Ошибке» значение DelY, которое равно “Y2 – Y1. Если ;ошибка превышает LenX, то увеличиваем координату Y (X) на ;единицу. Данный алгоритм пригоден только в том случае, если
;X2 > X1 и расстояние по горизонтали (X2 – X1) больше расстояния ;по вертикали (Y2 – Y1). Иначе же, если X2 < X1, то к координате ;X не прибавляем единицу, а наоборот, отнимаем. Если ;вертикальное расстояние больше горизонтального, то переменные ;Xи Yменяются ролями: на каждом шаге увеличиваем Yна единицу, ;а Xувеличивается в зависимости от «Ошибки».

LINE PROC

pushcx

pushax

pushbx

push dx

mov DelX, 1 ;Приращение X = 1

mov DelY, 1 ;Приращение Y = 1

mov ax, x2

cmp ax, x1

jge X2GX1 ;если X2 < X1

neg DelX ;DelX = -1

X2GX1:

mov ax, Y2

cmp ax, Y1

jge Y2GY1 ;Если Y2 < Y1

neg DelY ;DelY = -1

Y2GY1:

mov ax, X2

sub ax, x1

jns LENXG0

neg ax

LENXG0:

mov LenX, ax

mov ax, Y2

sub ax, Y1

jns LENYG0

neg ax

LENYG0:

mov LenY, ax

mov bx, LenX

cmp ax, bx

jg LenYGLenX