Код:
;рисуем четыре симметричные дуги, для которых продвижение по основной оси Х идет
;быстрее, то есть для которых Y - основная ось. Установим параметры рисования
;для начальной точки (А, 0). Вычислим все точки вдоль дуги 1/8 эллипса и
;разместим эту информацию в PixList
mov PixListPtr,offset PixList; PixListPtr = PixList
mov WorkingY,0; WorkingY = 0
mov YAdjust,0; YAdjust = 0
mov ebx,BB
mov eax,ebx
movsx edx,A
imul ebx,edx ;ebx = BB * A
shr eax,2 ;eax = BB / 4
sub eax,ebx ;eax = BB / 4 - BB * A
mov Threshold,eax ;Threshold = BB / 4 - BB * A
shl ebx,1 ;ebx = BB * 2 * A
mov XAdjust,ebx ;XAdjust = BB * 2 * A
b4: mov eax,YAdjust
add eax,AA
add Threshold,eax ;Threshold += YAdjust + AA
cmp Threshold,0
mov bx,PixListPtr
jl b5
mov eax,BB2
sub XAdjust,eax ;XAdjust -= BB * 2
mov eax,XAdjust
sub Threshold,eax ;Threshold -= XAdjust
mov byte ptr [bx],1 ;*PixListPtr++ = 1
jmp b6
b5: mov byte ptr [bx],0 ;*PixListPtr++ = 0
b6: inc PixListPtr
mov eax,AA2
add YAdjust,eax ;YAdjust += AA * 2;
inc WorkingY ;WorkingY++
mov eax,YAdjust
cmp eax,XAdjust ;if(YAdjust >= XAdjust ) break;
jl b4
push offset PixList
push 1
push -SCREEN_WIDTH_IN_BYTES
push WorkingY
push di
mov ax,si
sub ax,A
push ax
call DrawVOctant; DrawVOctant(X-A, Y, WorkingY, -SCREEN_WIDTH_IN_BYTES,1,PixList);
push offset PixList+1
push 1
push SCREEN_WIDTH_IN_BYTES
mov ax,WorkingY
dec ax
push ax
mov ax,di
inc ax
push ax
movzx ax, PixList
add ax,si
sub ax,A
push ax
call DrawVOctant; DrawVOctant(X-A+(*PixList), Y+1, WorkingY-1, SCREEN_WIDTH_IN_BYTES,1,PixList+1);
push offset PixList
push 0
push -SCREEN_WIDTH_IN_BYTES
push WorkingY
push di
mov ax,si
add ax,A
push ax
call DrawVOctant; DrawVOctant(X+A, Y, WorkingY, -SCREEN_WIDTH_IN_BYTES,0,PixList);
push offset PixList+1
push 0
push SCREEN_WIDTH_IN_BYTES
dec WorkingY
push WorkingY
inc di
push di
movzx ax,PixList
add si,A
sub si,ax
push si
call DrawVOctant; DrawVOctant(X+A-(*PixList), Y+1, WorkingY-1, SCREEN_WIDTH_IN_BYTES,0,PixList+1);
mov dx,GC_INDEX+1
mov al,0FFh
out dx,al ; outp(GC_INDEX+1,0xFF)
dec dx
mov ax,SET_RESET_ENABLE_INDEX
out dx,ax ; outpw(GC_INDEX, SET_RESET_ENABLE_INDEX)
pop di
pop si
leave
retn 10
DrawEllips endp
; Рисуем дугу в октанте, в котором Х - основная ось. (x,y) - это первый пиксел
;дуги. HorizontalMoveDirection выбирает направление движения вдоль дуги по
;горизонтали - влево или вправо (0=влево, 1=вправо). RowOffset содержит смещение
;в байтах от данной линии сканирования до следующей и проверяет, отрисовывается
;дуга вверх или вниз, DrawLength - это горизонтальная длина в пикселах дуги, а
;DrawList - это список, содержащий 0 для каждой точки, если следующая точка
;вертикально выровнена, и 1, если следующая точка на 1 пиксел по диагонали
;смещена влево или вправо
DrawHOctant proc
X equ word ptr [esp+6]
Y equ word ptr [esp+8]
DrawLength equ word ptr [esp+10]
RowOffset equ word ptr [esp+12]
HorizontalMoveDirection equ word ptr [esp+14]
DrawList equ word ptr [esp+16]
push si
push di
imul dx,Y,SCREEN_WIDTH_IN_BYTES
mov di,X
mov cx,di
sar di,3
add di,dx ;di = ScreenPtr = (Y * SCREEN_WIDTH_IN_BYTES)+(X/8))
and cx,7
mov ax,80h
sar ax,cl
mov cl,al ;cl = BitMask = 0x80 >> (X & 7)
mov si,DrawLength ;while (DrawLenght--)
b1: mov dx,GC_INDEX+1
mov al,cl ;al = BitMask
out dx,al ;outp(GC_INDEX + 1, BitMask)
or byte ptr es:[di],0FEh;*ScreenPtr |= 0xFE
mov bx,DrawList
inc DrawList
cmp byte ptr [bx],0 ;if(*DrawList++)
jz b2
add di,RowOffset ;ScreenPtr += RowOffset
b2: cmp HorizontalMoveDirection,1
jnz b3
shr cl,1 ;BitMask = BitMask >> 1
jnz b4 ;BitMask = 0?
mov cl,80h ;BitMask = 80h
inc di ;ScreenPtr++
jmp b4
b3: shl cl,1 ;BitMask = BitMask << 1
jnz b4 ;BitMask = 0?
mov cl,1 ;BitMask = 1
dec di ;ScreenPtr--
b4: dec si
jnz b1
pop di
pop si
retn 12
DrawHOctant endp
; Рисуем дугу в октанте, в котором Y - основная ось. (x,y) - это первый пиксел
;дуги. HorizontalMoveDirection выбирает направление движения вдоль дуги по
;горизонтали - влево или вправо (0=влево, 1=вправо). RowOffset содержит смещение
;в байтах от данной линии сканирования до следующей и проверяет, отрисовывается
;дуга вверх или вниз, DrawLength - это вертикальная длина в пикселах дуги, а
;DrawList - это список, содержащий 0 для каждой точки, если следующая точка
;вертикально выровнена, и 1, если следующая точка на 1 пиксел по диагонали
;смещена влево или вправо