Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > Низкоуровневое программирование > Assembler
Регистрация

Восстановить пароль
Повторная активизация e-mail

Ответ
 
Опции темы
Старый 12.12.2014, 12:14   #1
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию Эллипс в DOS (masm, tasm, fasm)

Давайте устроим мини-компо - 65 тысяч раз выводим на экран эллипс, замеряем тики в начале цикла и в конце, у кого изящнее и быстрее - тот и победил

Последний раз редактировалось Mikl___; 12.12.2014 в 14:07.
Mikl___ вне форума   Ответить с цитированием
Старый 12.12.2014, 14:07   #2
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Это чтобы было от чего оттолкнуться
Код:

; masm dos com #
.286
.model tiny
color equ 0Ah
a equ 63
b equ 99
.code
.686
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
	or bx,-1
	finit
	rdtsc; замеряем время
	mov dword ptr timer,eax
	mov dword ptr timer+4,edx
a1:	mov x,-a
	mov y,0
	mov al,color
	mov bp,x
	mov es:[bp+32160],al; X=-b Y=0
	neg bp
	mov es:[bp+32160],al; X=b Y=0
	mov cx,b-1
	fld1
@@:	inc x
	fild x
	fld st
	fmulp st(1),st; st(0)=x*x
	fidiv a2      ; st(0)=-x^2/a^2 st(1)=1 
	fadd st,st(1) ; st(0)=1-x^2/a^2
	fsqrt         ; st(0)=sqrt(1-x^2/a^2)
	fimul b1      ; st(0)=b*sqrt(1-x^2/a^2)
	fistp y
	mov bp,x
	imul di,y,320
	mov es:[bp+32160][di],al; X  Y
	neg di
	mov es:[bp+32160][di],al; X -Y
	neg bp
	mov es:[bp+32160][di],al;-X -Y
	neg di
	mov es:[bp+32160][di],al;-X  Y
	loop @b
;--------------------------------------
	dec bx
	jnz a1
	rdtsc; замеряем время
	sub eax,dword ptr timer
       	sbb edx,dword ptr timer+4
	shrd edx,eax,16
	shr edx,16
	mov dword ptr timer+4,edx
	mov dword ptr timer,eax
	fild timer
	fbstp tbyte ptr timer
        mov si,offset timer+8
        mov di,offset string
	mov dx,di
        mov cx,9
@@:	mov al,[si]          ; xxxx xxxx AAAA BBBB
	dec si
	rol ax, 12             ; BBBB xxxx xxxx AAAA
	rol ah, 4              ; xxxx BBBB xxxx AAAA
	and ax, 0f0fh          ; 0000 BBBB 0000 AAAA
	add ax, 3030h          ; 3B3A
	mov [di], ax
	add di, 2
	loop @b
	mov ah,9; выводим надпись на экран
	int 21h
; ждем нажатия на клавиатуру
	mov ah,0
	int 16h
	mov ax,3; восстанавливаем текстовый режим
	int 10h
	retn
x  dw -a
y  dw 0
a2 dw -a*a
b1 dw b
timer dq 0
db 0,0
string db 20 dup (" "),"tics$"
end start

Mikl___ вне форума   Ответить с цитированием
Старый 12.12.2014, 14:18   #3
Serge_Bliznykov
МегаМодератор
СуперМодератор
 
Регистрация: 09.01.2008
Сообщений: 24,383
Репутация: 5308
По умолчанию

Mikl___, а что, кто-то будет с Вами соревноваться?!
я лично - нет!
Serge_Bliznykov вне форума   Ответить с цитированием
Старый 12.12.2014, 14:42   #4
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Serge_Bliznykov,
попробуйте - истина рождается в споре, текст в #2 это нижняя планка, подсказываю - основные тормоза это FPU-вычисления и по-точечный вывод на экран
Mikl___ вне форума   Ответить с цитированием
Старый 12.12.2014, 15:54   #5
Stilet
Белик Виталий :)
Профессионал
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Адрес: Украина, Донецкая область, г. Краматорск
Сообщений: 57,957
Репутация: 6832
По умолчанию

Цитата:
основные тормоза это FPU-вычисления и по-точечный вывод на экран
Поэтому и буфферизируют отрисовку прежде чем вывести на экран.
Ничего удивительного.
__________________
I'm learning to live...
Stilet вне форума   Ответить с цитированием
Старый 12.12.2014, 19:30   #6
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Попытка номер два
строим эллипс инкрементируя Х от –b до 0, а для получения Y используем уравнение эллипса X^2/A^2+Y^2/B^2=1 откуда Y=B√(1–X^2/A^2), для скорости и используя симметрию выводим на экран через Set4Pixels сразу по четыре точки, все лишнее из цикла убрано, и так как умножение, по-любому, быстрее деления заменяем деление на A^2 умножением на 1/A^2. При построении смотрим не получился ли разрыв между точками и если Y(X) – Y(X-1) > 1, тогда строим линию с координатами (X-1, Y(X-1)) и (X-1, Y(X)).
Код:

; masm dos com #
.286
.model tiny
color equ 0Ah
a equ 99
b equ 63
color1 equ 0Ah
.code
.686
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
	or bx,-1
	finit
	rdtsc
	mov dword ptr timer,eax
	mov dword ptr timer+4,edx
@1:	push bx
	mov x1,-b
	mov y1,0
	mov a1,a
	mov b2,-b*b
	mov bp,x1
	imul di,y1,320
	call Set4Pixels1
	mov ecx,b
	fld1
	fld st		;st(0)=st(1)=1	
	fidiv b2        ;st(0)=-1/b?
	fstp b2         ;b2=-1/b?
@@:	inc x1
	mov bx,y1
	fild x1
	fld st
	fmulp st(1),st; st(0)=x*x
	fmul b2       ; st(0)=-x^2/b^2 st(1)=1 умножение быстрее деления
	fadd st,st(1) ; st(0)=1-x^2/b^2
	fsqrt         ; st(0)=sqrt(1-x^2/b^2)
	fimul a1      ; st(0)=a*sqrt(1-x^2/b^2)
	fistp y1
	sub bx,y1	;удаляем разрывы между точками
	cmp bx,-b
	jb l4
	mov bp,x1
	dec bp
l5:	mov di,y1
	add di,bx
	imul di,320
	call Set4Pixels1
	inc bx
	jnz l5
l4:	mov bp,x1
	imul di,y1,320
	call Set4Pixels1
	loop @b
	pop bx
	dec bx
	jnz @1
	rdtsc
	sub eax,dword ptr timer
       	sbb edx,dword ptr timer+4
	shrd edx,eax,16
	shr edx,16
	mov dword ptr timer+4,edx
	mov dword ptr timer,eax
	fild timer
	fbstp tbyte ptr timer
        mov si,offset timer+8
        mov di,offset string
	mov dx,di
        mov cx,9
@@:	mov al,[si]          ; xxxx xxxx AAAA BBBB
	dec si
	rol ax, 12             ; BBBB xxxx xxxx AAAA
	rol ah, 4              ; xxxx BBBB xxxx AAAA
	and ax, 0f0fh          ; 0000 BBBB 0000 AAAA
	add ax, 3030h          ; 3B3A
	mov [di], ax
	add di, 2
	loop @b
	mov ah,9
	int 21h
	mov ah,0
	int 16h
	mov ax,3
	int 10h
	retn
Set4Pixels1 proc
	mov byte ptr es:[bp+32160][di],color1; X  Y
	neg di
	mov byte ptr es:[bp+32160][di],color1; X -Y
	neg bp
	mov byte ptr es:[bp+32160][di],color1;-X -Y
	neg di
	mov byte ptr es:[bp+32160][di],color1;-X  Y
	retn
Set4Pixels1 endp
x1 dw -b
y1 dw 0
b2 dd -b*b
a1 dd a
timer dq 0
db 0,0
string db 20 dup (" "),"tics$"
end start


Последний раз редактировалось Mikl___; 12.12.2014 в 19:38.
Mikl___ вне форума   Ответить с цитированием
Старый 12.12.2014, 19:36   #7
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Заменяем вещественную арифметику на целочисленную. Строим эллипс по алгоритму Брезенхейма.
Код:

; masm dos com #
.286
.model tiny
color2 equ 0Ah
a equ 99
b equ 63
aa equ a*a
bb equ b*b
aa2 equ 2*aa
bb2 equ 2*bb
aa4 equ 4*aa
bb4 equ 4*bb
.code
.686
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
	or bx,-1
	rdtsc
	mov dword ptr timer,eax
	mov dword ptr timer+4,edx
a1:	push bx
	mov x,b
	mov y,0
	mov eax,x	;d=aa2*((x-1)*(x))+aa+bb2*(1-aa)
	dec eax
	imul x
	imul eax,aa2
	add eax,aa
	add d,eax
	mov eax,-aa
	inc eax
	imul eax,bb2
	add d,eax
	jmp l1		;while(aa*x > bb*y)
l0:	call Set4Pixels2
	cmp d,0		;if (d>=0)
	jl @f
	dec x		;x--
	imul esi,x,aa4
	sub d,esi	; d-=aa4*(x);
@@:	mov esi,y
	lea esi,[esi*2+3]
	imul esi,bb2
   	add d,esi	;d+=bb2*(3+y*2)
   	inc y		;y++
l1:	imul esi,x,aa
	imul edi,y,bb 
	cmp esi,edi
	jg l0
	mov eax,y	;d=bb2*(y+1)*y+aa2*(x*(x-2)+1)+(1-aa2)*bb
	inc eax
	imul y
	imul eax,bb2
	add d,eax
	mov eax,-aa2
	inc eax
	imul eax,bb
	add d,eax
	mov eax,x
	sub eax,2
	imul eax,x
	inc eax
	imul eax,aa2
	add d,eax
	jmp l2
l3:	call Set4Pixels2
	cmp d,0		;if (d<=0)
	jg @f
	inc y		;y++
	imul eax,y,bb4
	add d,eax	;d+=bb4*y
@@:	dec x		;x--
	mov eax,x
	lea eax,[eax*2-3];d+=aa2*(3-x*2)
	imul eax,-aa2
	add d,eax
l2:	cmp x,-1
	jnz l3
	pop bx
	dec bx
	jnz a1
	rdtsc
	sub eax,dword ptr timer
       	sbb edx,dword ptr timer+4
	shrd edx,eax,16
	shr edx,16
	mov dword ptr timer+4,edx
	mov dword ptr timer,eax
	fild timer
	fbstp tbyte ptr timer
        mov si,offset timer+8
        mov di,offset string
	mov dx,di
        mov cx,9
@@:	mov al,[si]          ; xxxx xxxx AAAA BBBB
	dec si
	rol ax, 12             ; BBBB xxxx xxxx AAAA
	rol ah, 4              ; xxxx BBBB xxxx AAAA
	and ax, 0f0fh          ; 0000 BBBB 0000 AAAA
	add ax, 3030h          ; 3B3A
	mov [di], ax
	add di, 2
	loop @b
	mov ah,9
	int 21h
	mov ah,0
	int 16h
	mov ax,3
	int 10h
	retn
Set4Pixels2 proc
	mov bp,word ptr x
	imul di,word ptr y,320
	mov byte ptr es:[bp+32160][di],color2; X  Y
	neg di
	mov byte ptr es:[bp+32160][di],color2; X -Y
	neg bp
	mov byte ptr es:[bp+32160][di],color2;-X -Y
	neg di
	mov byte ptr es:[bp+32160][di],color2;-X  Y
	retn
Set4Pixels2 endp
x  dd b
y  dd 0
d  dd ?
timer dq 0
db 0,0
string db 20 dup (" "),"tics$"
end start

Mikl___ вне форума   Ответить с цитированием
Старый 12.12.2014, 19:45   #8
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

немного упростим реализацию алгоритма Брезенхейма
Код:

; masm dos com #
.286
.model tiny
color equ 0Ah
a equ 99
b equ 63
aa equ a*a
bb equ b*b
aa2 equ 2*aa
bb2 equ 2*bb
.code
.686
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
	or bx,-1
	rdtsc
	mov dword ptr timer,eax
	mov dword ptr timer+4,edx
a1:	push bx
	mov deltaX,aa2*b
	mov deltaY,bb2*a
	mov esi,(bb/4)-bb*a+aa
	xor ebp,ebp;x=0
	mov edi,a*320;y=a
	xor eax,eax;deltaX=0
;рисуем верхнюю и нижнюю точки
	mov byte ptr es:[di+32160],color; 0  Y
;избавляемся от двух команд neg edi так как di равно a*320 то di-a*640=-a*320
	mov byte ptr es:[di+32160-a*640],color; 0 -Y
;увеличиваем ошибку накопления до значения следующей точки по оси X
l0:	add esi,eax	;d+=deltaX
;рисуем четыре симметричные точки
	mov byte ptr es:[bp+32161][di],color	; X  Y
;избавляемся от команды inc ebp увеличив смещение по Х за счет смещения 
;центра эллипса
	neg edi                                 
	mov byte ptr es:[bp+32161][di],color	; X -Y
	not ebp; увеличиваем значение в ebp за счет того что not(X)=-(X+1)		
	mov byte ptr es:[bp+32160][di],color	;-X -Y
	neg edi
	mov byte ptr es:[bp+32160][di],color	;-X  Y
	neg ebp
;если ошибка накопления прошла 0, затем если координата Y прошла 
;более чем полпути к следующему пикселю, то самое время перейти 
;по оси Y на 1 пиксель и установить следующую ошибку накопления
	test esi,esi	;if (d>=0)
	js @f
	sub edi,320     ;y--
;уменьшаем deltaY в соответствие с координатой Y
	sub deltaY,bb2  ;deltaY=2yb^2
;уменьшаем ошибку накопления до значения следующей точки по оси Y
	sub esi,deltaY	;d-=2yb^2
;увеличиваем deltaX в соответствие с координатой Х
@@:	add eax,aa2	;deltaX=2xa^2
	cmp eax,deltaY  ;while(xa^2 > yb^2)
	jl l0;Остановимся, если Х перестала быть основной 
;осью (дуга прошла точку наклона касательной в 45 градусов)
;-------------------------
	mov ebp,b	;x=b
;рисуем правую и левую точки
	mov byte ptr es:[bp+32160],color	; X  0
	mov byte ptr es:[bp+32160-2*b],color	;-X  0
	xor edi,edi     ;y=0
	xor eax,eax 	;deltaY=0
	mov esi,(aa/4)-aa*b+bb
;--------------------------------
;увеличиваем ошибку накопления до значения следующей точки по оси Y
l1:	add esi,eax	;d+=deltaY
;увеличиваем deltaY в соответствие с координатой Y
        add eax,bb2	;deltaY=2yb^2
	add edi,320     ;y++
;рисуем четыре симметричные точки
	mov byte ptr es:[bp+32160][di],color; Х  Y
	neg edi
	mov byte ptr es:[bp+32160][di],color; X  -Y
	neg ebp
	mov byte ptr es:[bp+32160][di],color;-X -Y
	neg edi
	mov byte ptr es:[bp+32160][di],color;-X  Y
	neg ebp		
;если ошибка накопления прошла 0, затем если координата Х прошла 
;более чем полпути к следующему пикселю, то самое время перейти 
;по оси Х на 1 пиксель и установить следующую ошибку накопления
	test esi,esi	;if (d<=0)
	js @f
;уменьшаем deltaX в соответствие с координатой X
	sub deltaX,aa2  ;deltaX=2xa^2
	sub esi,deltaX  ;d-=deltaX
	dec ebp         ;x--
;увеличиваем координату Y
@@:	cmp eax,deltaX  ;while(yb^2 > xa^2)
	jl l1;Остановимся, если Y перестала быть основной 
;осью (дуга прошла точку наклона касательной в 45 градусов)
	pop bx
	dec bx
	jnz a1
	rdtsc
	sub eax,dword ptr timer
       	sbb edx,dword ptr timer+4
	shrd edx,eax,16
	shr edx,16
	mov dword ptr timer+4,edx
	mov dword ptr timer,eax
	fild timer
	fbstp tbyte ptr timer
        mov si,offset timer+8
        mov di,offset string
	mov dx,di
        mov cx,9
@@:	mov al,[si]          ; xxxx xxxx AAAA BBBB
	dec si
	rol ax, 12             ; BBBB xxxx xxxx AAAA
	rol ah, 4              ; xxxx BBBB xxxx AAAA
	and ax, 0f0fh          ; 0000 BBBB 0000 AAAA
	add ax, 3030h          ; 3B3A
	mov [di], ax
	add di, 2
	loop @b
	mov ah,9
	int 21h
	mov ah,0
	int 16h
	mov ax,3
	int 10h
	retn
deltaX dd aa2*b;2x*a^2
deltaY dd bb2*a;2y*b^2
timer dq 0
db 0,0
string db 20 dup (" "),"tics$"
end start

Mikl___ вне форума   Ответить с цитированием
Старый 13.12.2014, 09:36   #9
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Еще упростим алгоритм Брезенхейма
  1. уравнение эллипса xx/bb+yy/aa=1 или xxaa+yybb-aabb=0 чтобы найти "точку перелома" берем производную d(xxaa+yybb-aabb)/dx=0 2aax+2bby*(dy/dx)=0 отсюда dy/dx=-2aax/(2bby)=-aax/(bby) ; в точке, где дуга прошла точку наклона касательной в 45 градусов dy/dx=-1 и существует равенство bbx=aay
  2. параметры рисования для начальной точки (0,А) точка из предыдущей итерации (x,y) сравнивается с точкой (x+1,y-0.5) разница равна aa(x+1)(x+1)+bb(y-0.5)(y-0.5)-aabb-aaxx-bbyy+aabb=aaxx+2aax+aa+bbyy-bby+0.25bb-aaxx-bbyy=2aax+aa-bby+bb/4 ; в точке x=0 y=a d=2aa*0+aa-bba+bb/4=aa-bba+bb/4
  3. параметры рисования для начальной точки (B,0) точка из предыдущей итерации (x,y) сравнивается с точкой (x-0.5,y+1) разница равна aa(x-0.5)(x-0.5)+bb(y+1)(y+1)-aabb-aaxx-bbyy+aabb=aaxx-aax+aa/4+bbyy+2bby+bb-aaxx-bbyy=-aax+aa/4+2bby+bb; в точке x=b y=0 d=-aab+aa/4+bb
Код:

; masm dos com #
.model tiny
a equ 63
b equ 99
aa equ a*a
bb equ b*b
aa2 equ 2*aa
bb2 equ 2*bb
color equ 0Ch
.code
.386
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
	mov esi,(bb/4)-bb*a+aa
	xor ebp,ebp;x=0
	mov edi,a*320;y=a
	xor eax,eax;deltaX=0
;рисуем верхнюю и нижнюю точки
	mov byte ptr es:[di+32160],color; 0  Y
;избавляемся от двух команд neg edi так как di равно a*320 то di-a*640=-a*320
	mov byte ptr es:[di+32160-a*640],color; 0 -Y
;увеличиваем ошибку накопления до значения следующей точки по оси X
l0:	add esi,eax	;d+=deltaX
;рисуем четыре симметричные точки
	mov byte ptr es:[bp+32161][di],color	; X  Y
;избавляемся от команды inc ebp увеличив смещение по Х за счет смещения 
;центра эллипса
	neg edi                                 
	mov byte ptr es:[bp+32161][di],color	; X -Y
	not ebp; увеличиваем значение в ebp за счет того что not(X)=-(X+1)		
	mov byte ptr es:[bp+32160][di],color	;-X -Y
	neg edi
	mov byte ptr es:[bp+32160][di],color	;-X  Y
	neg ebp
;если ошибка накопления прошла 0, затем если координата Y прошла 
;более чем полпути к следующему пикселю, то самое время перейти 
;по оси Y на 1 пиксель и установить следующую ошибку накопления
	test esi,esi	;if (d>=0)
	js @f
	sub edi,320     ;y--
;уменьшаем deltaY в соответствие с координатой Y
	sub deltaY,bb2  ;deltaY=2bby
;уменьшаем ошибку накопления до значения следующей точки по оси Y
	sub esi,deltaY	;d-=2bby
;увеличиваем deltaX в соответствие с координатой Х
@@:	add eax,aa2	;deltaX=2aax
	cmp eax,deltaY  ;while(aax > bby)
	jl l0;Остановимся, если Х перестала быть основной 
;осью (дуга прошла точку наклона касательной в 45 градусов)
;-------------------------
	mov ebp,b	;x=b
;рисуем правую и левую точки
	mov byte ptr es:[bp+32160],color	; X  0
	mov byte ptr es:[bp+32160-2*b],color	;-X  0
	xor edi,edi     ;y=0
	xor eax,eax 	;deltaY=0
	mov esi,(aa/4)-aa*b+bb
;--------------------------------
;увеличиваем ошибку накопления до значения следующей точки по оси Y
l1:	add esi,eax	;d+=deltaY
;увеличиваем deltaY в соответствие с координатой Y
        add eax,bb2	;deltaY=2bby
	add edi,320     ;y++
;рисуем четыре симметричные точки
	mov byte ptr es:[bp+32160][di],color; Х  Y
	neg edi
	mov byte ptr es:[bp+32160][di],color; X  -Y
	neg ebp
	mov byte ptr es:[bp+32160][di],color;-X -Y
	neg edi
	mov byte ptr es:[bp+32160][di],color;-X  Y
	neg ebp		
;если ошибка накопления прошла 0, затем если координата Х прошла 
;более чем полпути к следующему пикселю, то самое время перейти 
;по оси Х на 1 пиксель и установить следующую ошибку накопления
	test esi,esi	;if (d<=0)
	js @f
;уменьшаем deltaX в соответствие с координатой X
	sub deltaX,aa2  ;deltaX=2aa*x
	sub esi,deltaX  ;d-=deltaX
	dec ebp         ;x--
;увеличиваем координату Y
@@:	cmp eax,deltaX  ;while(bby > aax)
	jl l1;Остановимся, если Y перестала быть основной 
;осью (дуга прошла точку наклона касательной в 45 градусов)
;---------------------------------------
	mov ah,0        ;ждем нажатие на любую клавишу
	int 16h
	mov ax,3	;восстанавливаем текстовый режим
	int 10h
	retn		;выходим из программы
;--------------------------------------------------
deltaX dd aa2*b;2x*aa
deltaY dd bb2*a;2y*bb
end start

Выше эллипс выводился без использования битовой маски в 256-цветном 13h графическом режиме. Приведенная программа выводит эллипсы в следующих графических режимах
  • 0Dh 320x200 16 цветов
  • 0Eh 640x200 16 цветов
  • 0Fh 640x350 монохромный
  • 10h 640x350 16 цветов
  • 11h 640x480 монохромный
  • 12h 640x480 16 цветов
переделанная программа из Р.Уилтон "Видеосистемы персональных компьютеров IBM PC и PS/2. Руководство по программированию" М.: Радио и связь, 1994.
Код:

; masm dos com #
.model tiny
.code
.386
org 100h
Xcenter	equ 320	;x-координата центра
Ycenter	equ 240	;y-координата центра
a	equ 100	;a-радиус
b	equ 200	;b-радиус
color	equ 10	;цвет
aa	equ a*a
bb	equ b*b
aa2	equ 2*aa
bb2	equ 2*bb
BytesPerLine equ 80


Последний раз редактировалось Mikl___; 13.12.2014 в 09:49.
Mikl___ вне форума   Ответить с цитированием
Старый 13.12.2014, 09:41   #10
Mikl___
Профессионал
 
Регистрация: 11.01.2010
Сообщений: 1,128
Репутация: 926
По умолчанию

Отделим мух от котлет
алгоритм Брезенхейма на каждом шаге вычисляет положение точки, затем происходит вывод этой точки на экран и вычисление координат продолжается. Разделим создание эллипса на два этапа. Вычисление координат и рисование эллипса. Кроме того, если присмотреться, точки эллипса образуют набор вертикальных и горизонтальных линий разной длины смещенных относительно друг друга на один пиксель. Вычисляем длину каждой линии, которую потом поместим в массив ArrayX для горизонтальных и ArrayY для вертикальных линий, значения из массивов из-за симметрии будем читать или от начала к концу или от конца к началу. При этом явно задаются координаты только первой точки (в этом примере x=0 y=a)
Код:

; masm dos com #
.model tiny
screen_width equ 320
screen_height equ 200
a equ 63
b equ 99
aa equ a*a
bb equ b*b
aa2 equ 2*aa
bb2 equ 2*bb
color equ 0Ch
.code
.386
org 100h
start:	mov ax,13h
	int 10h
	push 0A000h
	pop es
;--------------Алгоритм Брезенхейма для рисования эллипса--------------------
	mov ebx,bb2*a	;deltaY=2bba
	mov esi,(bb/4)-bb*a+aa
	mov edi,offset ArrayX;адрес массива для длин отрезков
	xor eax,eax	;deltaX=0
l0:	add esi,eax	;d+=deltaX
	inc byte ptr [edi];вычисляем длину отрезка
	test esi,esi	;if (d >= 0)
	js @f
	inc edi		;переходим к следующей ячейке
	inc countX	;увеличиваем счетчик отрезков
	sub ebx,bb2	;deltaY=2ybb
	sub esi,ebx	;d-=2ybb
@@:	add eax,aa2	;deltaX=2xaa
	cmp eax,ebx	;while(aax > bby)
	jl l0		;Остановимся, если Х перестала быть основной 
;осью (дуга прошла точку наклона касательной в 45 градусов)
	mov ebx,aa2*b	;deltaX=2xaа
	mov edi,offset ArrayY;адрес массива для длин отрезков
	xor eax,eax 	;deltaY=0
	mov esi,(aa/4)-aa*b+bb
l1:	add esi,eax	;d+=deltaY
        add eax,bb2	;deltaY=2ybb
	inc byte ptr [edi];вычисляем длину отрезка
	test esi,esi	;if (d <= 0)
	js @f
	inc edi         ;переходим к следующей ячейке
	inc countY      ;увеличиваем счетчик отрезков
	sub ebx,aa2	;deltaX=2xaa
	sub esi,ebx	;d-=deltaX
@@:	cmp eax,ebx	;while(ybb > xaa)
	jl l1
;заполняем первый квадрант---------------------
	mov edi,a*screen_width+screen_width*(screen_height/2)+(screen_width/2);x=0 y=a
	mov al,color	;цвет эллипса
	stosb		;рисую точку (0,-a)
	mov ebx,offset ArrayX ;двигаюсь вправо и вверх
	call subrutineX ;читаю ArrayX от начала в конец
	add edi,screen_width-1
	dec delta;-(screen_width+1);двигаюсь вправо и вверх
	mov esi,offset ArrayY-1
	add esi,countY
 	call subrutineY        ;читаю ArrayY с конца и до начала
;заполняем второй квадрант------------------------
	std
	dec edi
	stosb
	sub edi,(screen_width-1)
	neg delta1;delta1=-1   ;двигаюсь влево
	mov delta,-(screen_width-1)  ;и вверх
	inc esi
	call subrutineY        ;читаю ArrayY от начала в конец
	add edi,(screen_width+1)
	dec delta;-screen_width  ;двигаюсь влево и вверх
	dec ebx
	call subrutineX ;читаю ArrayX с конца и до начала
;заполняем третий квадрант-------------------------
	add edi,screen_width
	stosb
	neg delta;screen_width	;двигаюсь влево и вниз
	inc ebx
	call subrutineX ;читаю ArrayX от начала в конец
	sub edi,(screen_width-1)
	inc delta;screen_width+1   ;двигаюсь влево и вниз
	dec esi
	call subrutineY ;читаю ArrayY с конца и до начала
;заполняем четвертый квадрант---------------------
	cld
	inc edi
	stosb
	add edi,(screen_width-1)
	neg delta1;,1	;двигаюсь влево
	mov delta,(screen_width-1)   ;и вниз
	inc esi
	call subrutineY ;читаю ArrayY от начала в конец
	sub edi,(screen_width+1)
	inc delta;screen_width	;двигаюсь вправо и вверх
	dec ebx
	call subrutineX ;читаю ArrayX с конца и до начала
;-----------------------------------------------------------
	mov ah,0        ;ждем нажатие на любую клавишу
	int 16h
	mov ax,3	;восстанавливаем текстовый режим
	int 10h
	retn		;выходим из программы
;--------------------------------------------------
subrutineX proc
	neg delta2
	mov ecx,countX
@@:	push ecx
	mov cl,[ebx]
	rep stosb	;двигаемся по горизонтали
	add edi,delta	;смещаемся по вертикали на 1 пиксель вверх или вниз
	add ebx,delta2  ;двигаемся по массиву вперед или назад
	pop ecx
	loop @b
	retn
subrutineX endp
subrutineY proc
	neg delta2
	mov ecx,countY
l2:	push ecx
	mov cl,[esi]
@@:	stosb           ;смещаемся по горизонтали на 1 пиксель
	add edi,delta	;двигаемся по вертикали вверх или вниз
	loop @b
	add edi,delta1	;edi = edi +/- 1
	add esi,delta2  ;двигаемся по массиву вперед или назад
	pop ecx
	loop l2
	retn
subrutineY endp
;------------------------------
delta	dd -screen_width
delta1	dd 1
delta2	dd -1
countX	dd 0
countY	dd 0
ArrayX db a/2 dup(0)
ArrayY db a/2 dup(0)
end start

Mikl___ вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Fasm и Masm Arsenx777 Assembler 2 27.06.2011 12:26
Из masm в fasm ( К среде ) Sobaka_ru Помощь студентам 0 12.12.2010 16:43
tasm>>fasm better Assembler 11 09.02.2009 20:34
Обьясните различия между - FASM, WASM, VASM, MASM, TASM Amancha Assembler 9 17.01.2009 16:38
Чем отличается Tasm от Masm veter_s_morya Assembler 17 21.07.2008 16:55


19:05.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru