Скачать .docx  

Курсовая работа: Графика на языке Assembler

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

ГОУ ВПО

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

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

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

«Графика на языке 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

mov Leng, bx

jmp C1

LenYGLenX:

mov Leng, ax

C1:

cmp ax, bx

jg LYGLX ;Если ABS(X2-X1) > ABS(Y2-Y1)

mov ax, X1

mov bx, Y1

mov dx, LenX

neg dx

inc Leng

mov cx, Leng

shl LenX, 1

shl LenY, 1

CYCLE1:

mov X2D, ax ;X = X1

mov Y2D, bx ;Y = Y1

CALL PUTPIXEL ;Рисуемточку

add ax, DelX ;X = X + DelX

add dx, LenY ;D = D + 2*(Y2-Y1)

cmp dx, 0 ;Если D > 0

jle DL01 ;

sub dx, LenX ;D = D - 2*(X2-X1)

add bx, DelY ;Y = Y + DelY

DL01:

loop CYCLE1

jmp EXITLINE

LYGLX: ;Если ABS(X2-X1) <= ABS(Y2-Y1)

mov ax, X1

mov bx, Y1

mov dx, LenY

neg dx

inc Leng

mov cx, Leng

shl LenX, 1

shl LenY, 1

CYCLE2:

mov X2D, ax ;X = X1

mov Y2D, bx ;Y = Y1

CALL PUTPIXEL ;Рисуемточку

add bx, DelY ;Y = Y + DelY

add dx, LenX ;D = D + 2*(X2-X1)

cmp dx, 0 ;Если D > 0

jle DL02

sub dx, LenY ;D = D - 2*(Y2-Y1)

add ax, DelX ;X = X + DelX

DL02:

loop CYCLE2

EXITLINE:

pop dx

pop bx

pop ax

pop cx

ret

ENDP LINE

MAIN PROC

mov ax, datas

mov ds, ax ;Инициализация сегментов данных

mov ax, 0A000h ;A000h - сегмент видеобуфера

mov es, ax

mov ah, 00h ;Установка видеорежима

mov al, 13h ;Mode = 13h (320x200x256)

int 10h

MainLoop:

mov COLOR, 15 ;Рисованиеточки

CALL DRAWCUBE ;Рисуемкуб

CALL WAITVRT ;Ждёмразвёрткуэкрана

mov COLOR, 0 ;

CALL DRAWCUBE ;Стираемкуб

in al,60h ;Читаемскан-кодклавиатуры

cmp al, 4bh ;Есликлавиша "Left"

jne DONTROTL

mov ax, DeltaY

sub ANY, ax ;уменьшаем ANY на DeltaY

jns DONTROTD

add ANY, 360

jmp DONTROTD

DONTROTL:

cmp al, 4dh ;Есликлавиша "Right"

jne DONTROTR

mov ax, DeltaY

add ANY, ax ;увеличиваем ANY на DeltaY

cmp ANY, 360

jb DONTROTD

sub ANY, 360

jmp DONTROTD

DONTROTR:

cmp al, 48h ;Есликлавиша "Up"

jne DONTROTU

mov ax, DeltaX

add ANX, ax ;увеличиваем ANX на DeltaX

cmp ANX, 360

jb DONTROTD

sub ANX, 360

jmp DONTROTD

DONTROTU:

cmp al, 50h ;Есликлавиша "Down"

jne DONTROTD ;

mov ax, DeltaX ;

sub ANX, ax ;уменьшаем ANX на DeltaX

jns DONTROTD ;

add ANX, 360 ;

DONTROTD:

cmp al, 01h ;еслине Escape

jne MainLoop ;делаемцикл

EXIT:

movah, 00h ;Установка текстового видеорежима

mov al, 02h ;Mode - 02h

int 10h

mov ax, 4C00h ;Terminate

int 21h

ENDP MAIN

CODES ENDS

END MAIN