Курсовая работа: Графика на языке Assembler
Название: Графика на языке 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) на ;единицу. Данный алгоритм пригоден только в том случае, если 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 = в + 2*(Y2-Y1) cmp dx, 0 ;Если в > 0 jle DL01 ; sub dx, LenX ;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 = в + 2*(X2-X1) cmp dx, 0 ;Если в > 0 jle DL02 sub dx, LenY ;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 |