Algorytm Bresenhama - assembly

0

Dobry wieczór, pisze sobie w assembly algorytm Bresenhama, no, dokładniej to portuje go z przykładu na wiki o stąd , ale coś nie działa gdy x2 jest większe od x1, i ogólnie coś nie trybi z współrzędnymi x2 oraz x1, błędu wypatrzeć - nie moge.
Może ktoś baardziej doświadczony w asm zerknie i zobaczy co jest nie tak. Generalnie błąd sie tak objawia że rysowana jest tylko jedna kratka, lub cały ekran (na pewno więcej niż 2000 wordów).

Sprawdziłem sobie na SFML-u jak to chodzi, i tam jest okej dla współrzędnych co podaje w asm, także to nie problem z algorytmem.

Od razu odpowiem na pytanie dlaczego kod jest taki syfiasty z tymi popami przy każdej prawie operacji, otóż przeklepuje go z wiki i chce odtworzyć takie warunki jakby nieruszalne gdzie modyfikuje tylko te rejestry co na nich operacje wykonuje, w sensie, że jako takie bezpieczniki. No, i nie ma być szybkie tylko działać :D
W celach nauki to będzie służyć do 16 bitowego kernela ;p
//edit
kompiluje nasmem, kod ten wykonywany jest w real mode

algorytm:

; dx - x1, ax - y1, bx - x2, cx - y2
bresenham_line:
	mov word [.x], dx		; x = x1
	mov word [.y], ax		; y = y1
	cmp dx, bx				; (x1 < x2)?
	jnb .e0					; if not jump
	mov word [.xi], 1		; xi = 1
	mov word [.dx], bx		; dx = bx x2
	sub word [.dx], dx		; dx = x2-x1
	jmp .aft_e0
	
	.e0:
		mov word [.xi], -1	; xi = -1
		mov word [.dx], dx	; dx = x1
		sub word [.dx], bx	; dx = x1 - x2
	
	.aft_e0:
	cmp ax, cx			
	jnb .e1					; y1 < y2?
	mov word [.yi], 1		; tak, yi = 1
	mov word [.dy], cx		; dy = y2
	sub word [.dy], ax		; dy = y2 - y1
	jmp .aft_e1
	
	.e1:
		mov word [.yi], -1	; nie, y1 = -1
		mov word [.dy], ax	; dy = y1
		sub word [.dy], cx 	; dy = y1 - y2
	
	.aft_e1:
	pusha
	mov dx, word [.y]
	mov bx, word [.x]
	mov ax, 0x490c
	call fx_write_memory1
	popa
	
	mov bp, word [.dx]		; 
	cmp bp, word [.dy]
	jng .else0
	
		push ax
		mov ax, word [.dy]		; dy
		sub ax, word [.dx]		; dy - dx
		mul word [.tw]			; (dy - dx) * 2
		mov word [.ai], ax		; ai = -||-
		pop ax
		
		push ax
		mov ax, word [.dy]		; bi
		mul word [.tw]			;
		mov word [.bi], ax
		pop ax
		
		push ax
		mov ax, word [.bi]
		sub ax, word [.dx]
		mov word [.d], ax
		pop ax
		
		.loop0:
			push ax
			mov ax, word [.x]
			cmp ax, word [.x2]
			pop ax
			je .end
			
			cmp  word[.d],  0
			jnae .else_nested0
				
				push ax
				mov ax, word [.x]	; x
				add ax, word [.xi]	; x + xi
				mov word [.x], ax	; x = x + xi
				pop ax
				
				push ax
				mov ax, word [.y]	; y
				add ax, word [.yi]	; y + yi
				mov word [.y], ax	; y = y + yi
				pop ax
				
				push ax
				mov ax, word [.d]	; d
				add ax, word [.ai]	; d + ai
				mov word [.d], ax	; d = d + ai
				pop ax
				
				pusha
				mov dx, word [.y]
				mov bx, word [.x]
				mov ax, 0x490c
				call fx_write_memory1
				popa				
				jmp .loop0
				
			.else_nested0:
				
				push ax
				mov ax, word [.d]	; d
				add ax, word [.bi]	; d + bi
				mov word [.d], ax		; d = d + bi
				pop ax
				
				push ax
				mov ax, word [.x]	; x
				add ax, word [.xi]	; x + xi
				mov word [.x], ax	; x = x + xi
				pop ax
				
				pusha
				mov dx, word [.y]
				mov bx, word [.x]
				mov ax, 0x490c
				call fx_write_memory1
				popa	
				
				jmp .loop0
	.else0:
	
	push ax
	mov ax, word [.dx]		; dx
	sub ax, word [.dy]		; dx - dy
	mul word [.tw]			; (dx - dy) * 2
	mov word [.ai], ax		; ai
	pop ax
	
	push ax
	mov ax, word [.dx]		; dx
	mul word [.tw]			; dx * 2
	mov word [.bi], ax		; bi = dx * 2
	pop ax
	
	push ax
	mov ax, word [.bi]		; bi
	sub ax, word [.dy]		; bi - dy
	mov word [.d], ax		; d = bi - dy
	pop ax
	
	.loop1:
		push ax
		mov ax, word [.y]
		cmp ax, word [.y2]
		pop ax
		
		je .end
		cmp  [.d], word 0
		jnae .else_nested1

			push ax
			mov ax, word [.x]				; x
			add ax, word [.xi]				; x + xi
			mov word [.x], ax				; x = x + xi
			pop ax
			
			push ax
			mov ax, word [.y]				; y
			add ax, word [.yi]				; y + yi
			mov word [.y], ax				; y = y + yi
			pop ax
			
			push ax
			mov ax, word [.d]				; d
			add ax, word [.ai]				; d + ai
			mov word [.d], ax				; d = d + ai
			pop ax
			
			pusha
			mov dx, word [.y]
			mov bx, word [.x]
			mov ax, 0x490c
			call fx_write_memory1
			popa	
			
			jmp .loop1
		.else_nested1:
			
			push ax
			mov ax, word [.d]				; d
			add ax, word [.bi]				; d + bi
			mov word [.d], ax				; d = d + bi
			pop ax
			
			push ax
			mov ax, word [.y]				; y
			add ax, word [.yi]              ; y + yi
			mov word [.y], ax				; y = y + yi
			pop ax
			
			pusha
			mov dx, word [.y]
			mov bx, word [.x]
			mov ax, 0x490c
			call fx_write_memory1
			popa	
			
			jmp .loop1
	
	.end:
	ret
	.x1 dw 0
	.x2 dw 0
	.y1 dw 0
	.y2 dw 0
	.x  dw 0
	.y  dw 0
	.d  dw 0
	.dx dw 0
	.dy dw 0
	.ai dw 0
	.bi dw 0
	.xi dw 0
	.yi dw 0
	.tw dw 2

I funkcja którą maże sobie po pamięci VGA.

; dx y, bx - x
; ax - byte
; y + 160 + (x * 2)
fx_write_memory1:
	push es
	push ax
	mov ax, 0x0b800
	mov es, ax
	xor di, di
	mov ax, dx	; y
	mov cx, 160
	mul cx				; y * 160
	add di, ax			; di = offset_y
	mov ax, bx
	mov cx, 2
	mul cx
	add di, ax
	pop ax
	mov word [es:di], ax	
	pop es
	ret
0

emo8086 w dłoń. Nikt tego za ciebie nie będzie przeklikiwał.

1

Dobra, podebugowałem jescze z rana, wyspany już, i znalazłem błąd, zmienna x2 i y2 nie była inicjalizowana, dosyć głupi błąd.
Zostawiam wersje 16 bit i 32 bit. Może komuś sie przyda.
16 bit

; dx - x1, ax - y1, bx - x2, cx - y2
bresenham_line:

	mov word [.x], dx		; x = x1 ok
	mov word [.y], ax		; y = y1 ok
	mov word [.x2], bx
	mov word [.y2], cx
	
	cmp dx, bx				; (x1 < x2)? 
	jnb .e0					; if not jump
							; jeśli x1 < x2
	mov word [.xi], 1		; xi = 1
	mov word [.dx], bx		; dx = bx x2
	sub word [.dx], dx		; dx = x2-x1
	jmp .aft_e0
		
	.e0:
							; jeśli x1 > x2
		mov word [.xi], -1	; xi = -1
		mov word [.dx], dx	; dx = x1
		sub word [.dx], bx	; dx = x1 - x2
	
	.aft_e0:
	cmp ax, cx			
	jnb .e1					; y1 < y2?
	
	mov word [.yi], 1		; tak, yi = 1
	mov word [.dy], cx		; dy = y2
	sub word [.dy], ax		; dy = y2 - y1
	jmp .aft_e1

	.e1:		
		mov word [.yi], -1	; nie, y1 = -1
		mov word [.dy], ax	; dy = y1
		sub word [.dy], cx 	; dy = y1 - y2
	
	.aft_e1:
	
	pusha
	mov dx, word [.y]
	mov bx, word [.x]
        ; Draw char
	popa	

	mov bp, word [.dx]		; 
	cmp bp, word [.dy]
	jng .else0
		
		mov ax, word [.dy]		; dy
		sub ax, word [.dx]		; dy - dx
		mul word [.tw]			; (dy - dx) * 2
		mov word [.ai], ax		; ai = -||-
		
		mov ax, word [.dy]		; bi
		mul word [.tw]			;
		mov word [.bi], ax
		
		mov ax, word [.bi]
		sub ax, word [.dx]
		mov word [.d], ax
	
		.loop0:

			mov ax, word [.x]
			cmp ax, word [.x2]
			je .end
			
			cmp  word[.d],  0
			jnge .else_nested0
				
				mov ax, word [.x]	; x
				add ax, word [.xi]	; x + xi
				mov word [.x], ax	; x = x + xi
				
				mov ax, word [.y]	; y
				add ax, word [.yi]	; y + yi
				mov word [.y], ax	; y = y + yi
				
				mov ax, word [.d]	; d
				add ax, word [.ai]	; d + ai
				mov word [.d], ax	; d = d + ai
				
				pusha
				mov dx, word [.y]
				mov bx, word [.x]
                                ; Draw char
				popa	
				
				dec cx	
				jmp .loop0
				
			.else_nested0:
				
				mov ax, word [.d]	; d
				add ax, word [.bi]	; d + bi
				mov word [.d], ax		; d = d + bi
				
				mov ax, word [.x]	; x
				add ax, word [.xi]	; x + xi
				mov word [.x], ax	; x = x + xi
				
				pusha
				mov dx, word [.y]
				mov bx, word [.x]
                                ; Draw char
				popa	

				jmp .loop0
	.else0:
	
	mov ax, word [.dx]		; dx
	sub ax, word [.dy]		; dx - dy
	mul word [.tw]			; (dx - dy) * 2
	mov word [.ai], ax		; ai
	
	mov ax, word [.dx]		; dx
	mul word [.tw]			; dx * 2
	mov word [.bi], ax		; bi = dx * 2
	
	mov ax, word [.bi]		; bi
	sub ax, word [.dy]		; bi - dy
	mov word [.d], ax		; d = bi - dy
	
	.loop1:
		mov ax, word [.y]
		cmp ax, word [.y2]
		je .end
		
		cmp  word [.d],  0
		jnge .else_nested1


			mov ax, word [.x]				; x
			add ax, word [.xi]				; x + xi
			mov word [.x], ax				; x = x + xi
			
			mov ax, word [.y]				; y
			add ax, word [.yi]				; y + yi
			mov word [.y], ax				; y = y + yi
			
			mov ax, word [.d]				; d
			add ax, word [.ai]				; d + ai
			mov word [.d], ax				; d = d + ai
			
			pusha
			mov dx, word [.y]
			mov bx, word [.x]
                        ; Draw char
			popa	
			
			jmp .loop1
		.else_nested1:
			
			mov ax, word [.d]				; d
			add ax, word [.bi]				; d + bi
			mov word [.d], ax				; d = d + bi
			
			mov ax, word [.y]				; y
			add ax, word [.yi]              ; y + yi
			mov word [.y], ax				; y = y + yi

			
			pusha
			mov dx, word [.y]
			mov bx, word [.x]
	                ; Draw char
			popa		
			
			jmp .loop1
	
	.end:
	ret
	.x1 dw 0
	.x2 dw 0
	.y1 dw 0
	.y2 dw 0
	.x  dw 0
	.y  dw 0
	.d  dw 0
	.dx dw 0
	.dy dw 0
	.ai dw 0
	.bi dw 0
	.xi dw 0
	.yi dw 0
	.tw dw 2

32 bit linux

section .text
extern initscr
extern endwin
extern mvaddch
extern getchar 
extern mvaddstr
extern refresh
global main
; edx - x1, eax - y1, ebx - x2, ecx - y2
bresenham_line:

	mov dword [x], edx		; x = x1 ok
	mov dword [y], eax		; y = y1 ok
	mov dword [x2], ebx
	mov dword [y2], ecx
	
	cmp edx, ebx			; (x1 < x2)? 
	jnb .e0					; if not jump
							; jeśli x1 < x2
	mov dword [xi], 1		; xi = 1
	mov dword [dxx], ebx		; dx = bx x2
	sub dword [dxx], edx		; dx = x2-x1
	jmp .aft_e0
		
	.e0:
							; jeśli x1 > x2
		mov dword [xi], -1	; xi = -1
		mov dword [dxx], edx	; dx = x1
		sub dword [dxx], ebx	; dx = x1 - x2
	
	.aft_e0:
	cmp eax, ecx			
	jnb .e1					; y1 < y2?
	
	mov dword [yi], 1		; tak, yi = 1
	mov dword [dyy], ecx		; dy = y2
	sub dword [dyy], eax		; dy = y2 - y1
	jmp .aft_e1

	.e1:		
		mov dword [yi], -1	; nie, y1 = -1
		mov dword [dyy], eax	; dy = y1
		sub dword [dyy], ecx	; dy = y1 - y2
	
	.aft_e1:
	pusha
	
	push dword '.'
	push dword [y]
	push dword [x]
	call mvaddch
	add esp, 12
	
	call refresh
	popa	
;=======================================================================

	mov ebp, dword [dxx]		; 
	cmp ebp, dword [dyy]
	jng .else0
		
		mov eax, dword [dyy]		; dy
		sub eax, dword [dxx]		; dy - dx
		mul dword [tw]			; (dy - dx) * 2
		mov dword [ai], eax		; ai = -||-
		
		mov eax, dword [dyy]		; bi
		mul dword [tw]			;
		mov dword [bi], eax
		
		mov eax, dword [bi]
		sub eax, dword [dxx]
		mov dword [d], eax
	
		.loop0:

			mov eax, dword [x]
			cmp eax, dword [x2]
			je .end
			
			cmp  dword[d],  0
			jnge .else_nested0
				
				mov eax, dword [x]	; x
				add eax, dword [xi]	; x + xi
				mov dword [x], eax	; x = x + xi
				
				mov eax, dword [y]	; y
				add eax, dword [yi]	; y + yi
				mov dword [y], eax	; y = y + yi
				
				mov eax, dword [d]	; d
				add eax, dword [ai]	; d + ai
				mov dword [d], eax	; d = d + ai
				
				pusha
				push dword '.'
				push dword [y]
				push dword [x]
				call mvaddch
				add esp, 12
				call refresh
				popa		
				
				jmp .loop0
				
			.else_nested0:
				
				mov eax, dword [d]	; d
				add eax, dword [bi]	; d + bi
				mov dword [d], eax		; d = d + bi
				
				mov eax, dword [x]	; x
				add eax, dword [xi]	; x + xi
				mov dword [x], eax	; x = x + xi
				
				pusha
				push dword '.'
				push dword [y]
				push dword [x]
				call mvaddch
				add esp, 12
				call refresh
				popa	
				
				jmp .loop0
	.else0:
	
	mov eax, dword [dxx]		; dx
	sub eax, dword [dyy]		; dx - dy
	mul dword [tw]			; (dx - dy) * 2
	mov dword [ai], eax		; ai
	
	mov eax, dword [dxx]		; dx
	mul dword [tw]			; dx * 2
	mov dword [bi], eax		; bi = dx * 2
	
	mov eax, dword [bi]		; bi
	sub eax, dword [dyy]		; bi - dy
	mov dword [d], eax		; d = bi - dy
	
	.loop1:
		mov eax, dword [y]
		cmp eax, dword [y2]
		je .end
		
		cmp  dword [d],  0
		jnge .else_nested1


			mov eax, dword [x]				; x
			add eax, dword [xi]				; x + xi
			mov dword [x], eax				; x = x + xi
			
			mov eax, dword [y]				; y
			add eax, dword [yi]				; y + yi
			mov dword [y], eax				; y = y + yi
			
			mov eax, dword [d]				; d
			add eax, dword [ai]				; d + ai
			mov dword [d], eax				; d = d + ai
			
			pusha
			push dword '.'
			push dword [y]
			push dword [x]
			call mvaddch
			add esp, 12
			call refresh
			popa	
			
			jmp .loop1
		.else_nested1:
			
			mov eax, dword [d]				; d
			add eax, dword [bi]				; d + bi
			mov dword [d], eax				; d = d + bi
			
			mov eax, dword [y]				; y
			add eax, dword [yi]              ; y + yi
			mov dword [y], eax				; y = y + yi

			pusha
			push dword '.'
			push dword [y]
			push dword [x]
			call mvaddch
			add esp, 12
			call refresh
			popa			
			
			jmp .loop1
	
	.end:
	ret


main:	
	call initscr
	
	; edx - x1, eax - y1, ebx - x2, ecx - y2
	mov edx, 3
	mov eax, 3
	mov ebx, 10
	mov ecx, 15
	call bresenham_line
	
	call getchar
	
	call endwin
	mov eax, 0
	ret
	
section .data
	x1 	dd 0
	x2 	dd 0
	y1 	dd 0
	y2 	dd 0
	x  	dd 0
	y  	dd 0
	d  	dd 0
	dxx dd 0
	dyy dd 0
	ai 	dd 0
	bi 	dd 0
	xi 	dd 0
	yi 	dd 0
	tw 	dd 2
0

W celach nauki to będzie służyć do 16 bitowego kernela ;p

Ale po co ci w kernelu algorytm rysowania linii?

0

@Azarien Chcę takie fajne haksiorskie kolorowe migajace okienka w stylu <marquee> :P
btw. w sumie to chyba nie szkodzi żeby zapakować procedury obsługi screena do kernela, bo mam w planie ustawić je w IVT i potem sobie wywoływać z jakiś programów (np. bardzo prosty edyto, bo edytora do kernela to już w ogóle kiepski pomysł pakować), które zassembuje na opkody.

// edit chociaż tak jak teraz pomyślałem, to niegłupim pomysłem jest takie procedury wywalić do jakiegoś pliku i w kernelu zostawić tylko niezbędne rzeczy jak I/O

1

@Proxima

W pełni sprawny kod do rysowania linii (algorytm Bresenham'a).

Zoptymalizowany, by nie korzystać z RSP i komórek pamięci [BARDZO SZYBKI].

Na podstawie kodu źródłowego w C https://pl.wikipedia.org/wiki/Algorytm_Bresenhama

Linie:

    mov    ax,    VARIABLE_KERNEL_SERVICE_VIDEO_PIXEL_SET
i
    int    STATIC_KERNEL_SERVICE

Należy zamienić na własną, stawiającą piksel na podstawie współrzędnych w rejestrach r8/x i r9/y

; Copyright (C) 2013-2016 Wataha.net
; All Rights Reserved
;
; LICENSE Creative Commons BY-NC-ND 4.0
; See LICENSE.TXT
;
; Main developer:
;	Andrzej (akasei) Adamczyk [e-mail: akasei from wataha.net]
;-------------------------------------------------------------------------------

; Use:
; nasm - http://www.nasm.us/

; 64 bitowy kod programu
[BITS 64]

; rbx - kolor 32 bitowy
; r8 - x1
; r9 - y1
; r10 - x2
; r11 - y2
library_draw_line:
	; zachowaj oryginalne rejestry
	push	rax
	push	rdx
	push	rsi
	push	rdi
	push	r8
	push	r9
	push	r12
	push	r13
	push	r14
	push	r15

	; domyślna procedura wyświetlająca piksele
	mov	ax,	VARIABLE_KERNEL_SERVICE_VIDEO_PIXEL_SET

	; sprawdź oś x
	; x1 > x2
	cmp	r8,	r10
	ja	.reverse_x

	; kierunek osi x rosnąco
	mov	r12,	1	; xi =	1
	mov	r14,	r10	; dx =	x2
	sub	r14,	r8	; dx -=	x1

	; sprawdź oś y
	jmp	.check_y

.reverse_x:
	; kierunek osi x malejąco
	mov	r12,	-1	; xi =	-1
	mov	r14,	r8	; dx =	x1
	sub	r14,	r10	; dx -=	x2

.check_y:
	; sprawdź oś y
	; y1 > y2
	cmp	r9,	r11
	ja	.reverse_y

	; kierunek osi y rosnąco
	mov	r13,	1	; yi =	1
	mov	r15,	r11	; dy =	y2
	sub	r15,	r9	; dy -=	y1

	; kontynuuj
	jmp	.done

.reverse_y:
	; kierunek osi y malejąco
	mov	r13,	-1	; yi =	-1
	mov	r15,	r9	; dy =	y1
	sub	r15,	r11	; dy -=	y2

.done:
	; względem której osi rysować linię?
	; dy > dx
	cmp	r15,	r14
	ja	.osY

	; rysuj linię względem osi X
	mov	rsi,	r15	; ai =	dy
	sub	rsi,	r14	; ai -=	dx
	shl	rsi,	VARIABLE_MULTIPLE_BY_2
	mov	rdx,	r15	; d =	dy
	shl	rdx,	VARIABLE_MULTIPLE_BY_2
	mov	rdi,	rdx	; bi =	d
	sub	rdx,	r14	; d -=	dx

.loop_x:
	; wyświetl piksel o zdefiniowanym kolorze
	int	STATIC_KERNEL_SERVICE

	; jeśli wyświetlony piksel znajduje się w punkcie końca linii, koniec
	; x1 == x2
	cmp	r8,	r10
	je	.end

	; współczynnik ujemny?
	; d
	bt	rdx,	VARIABLE_QWORD_SIGN
	jc	.loop_x_minus

	; oblicz pozycję następnego piksela w linii
	add	r8,	r12	; x +=	xi
	add	r9,	r13	; y +=	yi
	add	rdx,	rsi	; d +=	ai

	; rysuj linię
	jmp	.loop_x

.loop_x_minus:
	; oblicz pozycję następnego piksela w linii
	add	rdx,	rdi	; d +=	bi
	add	r8,	r12	; x +=	xi

	; rysuj linię
	jmp	.loop_x

.osY:
	; rysuj linię względem osi Y
	mov	rsi,	r14	; ai =	dx
	sub	rsi,	r15	; ai -=	dy
	shl	rsi,	VARIABLE_MULTIPLE_BY_2
	mov	rdx,	r14	; d =	dx
	shl	rdx,	VARIABLE_MULTIPLE_BY_2
	mov	rdi,	rdx	; bi =	d
	sub	rdx,	r15	; d -=	dy
	
.loop_y:
	; wyświetl piksel o zdefiniowanym kolorze
	int	STATIC_KERNEL_SERVICE

	; jeśli wyświetlony piksel znajduje się w punkcie końca linii, koniec
	; y1 == y2
	cmp	r9,	r11
	je	.end

	; współczynnik ujemny?
	; d
	bt	rdx,	VARIABLE_QWORD_SIGN
	jc	.loop_y_minus

	; oblicz pozycję następnego piksela w linii
	add	r8,	r12	; x +=	xi
	add	r9,	r13	; y +=	yi
	add	rdx,	rsi	; d +=	ai

	; rysuj linię
	jmp	.loop_y

.loop_y_minus:
	; oblicz pozycję następnego piksela w linii
	add	rdx,	rdi	; d +=	bi
	add	r9,	r13	; y +=	yi

	; rysuj linię
	jmp	.loop_y

.end:
	; przywtóć oryginalne rejestry
	pop	r15
	pop	r14
	pop	r13
	pop	r12
	pop	r9
	pop	r8
	pop	rdi
	pop	rsi
	pop	rdx
	pop	rax

	; powrót z procedury
	ret
3

Proszę bardzo kod 16 bitowy (sprawny, testowałem na własnym sektorze rozruchowym):

Linie:

	; ZAMIEŃ NA WŁASNĄ PROCEDURĘ WYŚWIETLANIA PIKSELI
	; X = ESI, Y = EDI
	nop

Należy zamienić na własną procedurę wyświetlania pikseli. xP

Jeśli ktokolwiek chce wykorzystać libliotekę jako 32 bitową, wystarczy zmienić DYREKTYWĘ oraz polecenia PUSH i POP:

; 16 Bitowy kod programu
[BITS 16]

; edx - x1
; eax - y1
; ebx - x2
; ecx - y2
library_draw_line:
	; zachowaj oryginalne rejestry
	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di

[...]

    ; przywróć oryginalne rejestry
    pop    di
    pop    si
    pop    dx
    pop    cx
    pop    bx
    pop    ax
 
    ; powrót z procedury
    ret

na

; 32 Bitowy kod programu
[BITS 32]

; edx - x1
; eax - y1
; ebx - x2
; ecx - y2
library_draw_line:
	; zachowaj oryginalne rejestry
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	esi
	push	edi

[...]

    ; przywróć oryginalne rejestry
    pop    edi
    pop    esi
    pop    edx
    pop    ecx
    pop    ebx
    pop    eax
 
    ; powrót z procedury
    ret

Tak... to jest takie proste...

Oto i cały kod:

; Copyright (C) 2013-2016 Wataha.net
; All Rights Reserved
;
; LICENSE Creative Commons BY-NC-ND 4.0
; See LICENSE.TXT
;
; Main developer:
;	Andrzej (akasei) Adamczyk [e-mail: akasei from wataha.net]
;-------------------------------------------------------------------------------

; Use:
; nasm - http://www.nasm.us/

struc	BRESENHAM
	.x2	resd	1
	.y2	resd	1
	.dx	resd	1
	.dy	resd	1
	.ai	resd	1
	.bi	resd	1
	.SIZE	resb	1
endstruc

; 16 Bitowy kod programu
[BITS 16]

; edx - x1
; eax - y1
; ebx - x2
; ecx - y2
library_draw_line:
	; zachowaj oryginalne rejestry
	push	ax
	push	bx
	push	cx
	push	dx
	push	si
	push	di

	; przygotuj miejsce pod zmienne
	sub	esp,	BRESENHAM.SIZE

	; zachowaj pozycje początku linii
	mov	esi,	edx
	mov	edi,	eax

	; zachowaj pozycje końca linii
	mov	dword [esp + BRESENHAM.x2],	ebx
	mov	dword [esp + BRESENHAM.y2],	ecx

	; sprawdź oś x
	; x1 > x2
	cmp	esi,	dword [esp + BRESENHAM.x2]
	ja	.reverse_x

	; kierunek osi x rosnąco
	mov	dword [esp + BRESENHAM.dx],	ebx	; dx =	x2
	sub	dword [esp + BRESENHAM.dx],	esi	; dx -=	x1
	mov	ebx,	1	; xi =	1

	; sprawdź oś y
	jmp	.check_y

.reverse_x:
	; kierunek osi x malejąco
	mov	dword [esp + BRESENHAM.dx],	esi	; dx =	x1
	sub	dword [esp + BRESENHAM.dx],	ebx	; dx -=	x2
	mov	ebx,	-1	; xi =	-1

.check_y:
	; sprawdź oś y
	; y1 > y2
	cmp	edi,	dword [esp + BRESENHAM.y2]
	ja	.reverse_y

	; kierunek osi y rosnąco
	mov	dword [esp + BRESENHAM.dy],	ecx	; dy =	y2
	sub	dword [esp + BRESENHAM.dy],	edi	; dy -=	y1
	mov	ecx,	1	; yi =	1

	; kontynuuj
	jmp	.done

.reverse_y:
	; kierunek osi y malejąco
	mov	dword [esp + BRESENHAM.dy],	edi	; dy =	y1
	sub	dword [esp + BRESENHAM.dy],	ecx	; dy -=	y2
	mov	ecx,	-1	; yi =	-1

.done:
	; względem której osi rysować linię?
	; dy > dx
	mov	eax,	dword [esp + BRESENHAM.dy]
	cmp	eax,	dword [esp + BRESENHAM.dx]
	ja	.osY

	; rysuj linię względem osi X
	; ai = dy
	; d = dy
	mov	edx,	eax	; d =	dy
	sub	eax,	dword [esp + BRESENHAM.dx]	; ai -=	dx
	shl	eax,	VARIABLE_MULTIPLE_BY_2
	mov	dword [esp + BRESENHAM.ai],	eax
	shl	edx,	VARIABLE_MULTIPLE_BY_2	; d *	2
	mov	dword [esp + BRESENHAM.bi],	edx	; bi =	d
	mov	eax,	dword [esp + BRESENHAM.dx]
	sub	edx,	eax	; d -=	dx

.loop_x:
	; wyświetl piksel o zdefiniowanym kolorze
	; ZAMIEŃ NA WŁASNĄ PROCEDURĘ WYŚWIETLANIA PIKSELI
	; X = ESI, Y = EDI
	nop

	; jeśli wyświetlony piksel znajduje się w punkcie końca linii, koniec
	; x1 == x2
	cmp	esi,	dword [esp + BRESENHAM.x2]
	je	.end

	; współczynnik ujemny?
	; d
	bt	edx,	VARIABLE_DWORD_SIGN
	jc	.loop_x_minus

	; oblicz pozycję następnego piksela w linii
	add	esi,	ebx	; x +=	xi
	add	edi,	ecx	; y +=	yi
	add	edx,	dword [esp + BRESENHAM.ai]	; d +=	ai

	; rysuj linię
	jmp	.loop_x

.loop_x_minus:
	; oblicz pozycję następnego piksela w linii
	add	edx,	dword [esp + BRESENHAM.bi]	; d +=	bi
	add	esi,	ebx	; x +=	xi

	; rysuj linię
	jmp	.loop_x

.osY:
	; rysuj linię względem osi Y
	mov	eax,	dword [esp + BRESENHAM.dx]	; ai = dx
	mov	edx,	eax	; d =	dx
	sub	eax,	dword [esp + BRESENHAM.dy]	; ai -=	dy
	shl	eax,	VARIABLE_MULTIPLE_BY_2
	mov	dword [esp + BRESENHAM.ai],	eax
	shl	edx,	VARIABLE_MULTIPLE_BY_2	; d *	2
	mov	dword [esp + BRESENHAM.bi],	edx	; bi =	d
	mov	eax,	dword [esp + BRESENHAM.dy]
	sub	edx,	eax	; d -=	dy
	
.loop_y:
	; wyświetl piksel o zdefiniowanym kolorze
	; ZAMIEŃ NA WŁASNĄ PROCEDURĘ WYŚWIETLANIA PIKSELI
	; X = ESI, Y = EDI
	nop

	; jeśli wyświetlony piksel znajduje się w punkcie końca linii, koniec
	; y1 == y2
	cmp	edi,	dword [esp + BRESENHAM.y2]
	je	.end

	; współczynnik ujemny?
	; d
	bt	edx,	VARIABLE_DWORD_SIGN
	jc	.loop_y_minus

	; oblicz pozycję następnego piksela w linii
	add	esi,	ebx	; x +=	xi
	add	edi,	ecx	; y +=	yi
	add	edx,	dword [esp + BRESENHAM.ai]	; d +=	ai

	; rysuj linię
	jmp	.loop_y

.loop_y_minus:
	; oblicz pozycję następnego piksela w linii
	add	edx,	dword [esp + BRESENHAM.bi]	; d +=	bi
	add	edi,	ecx	; y +=	yi

	; rysuj linię
	jmp	.loop_y

.end:
	; usuń zmienne lokalne
	add	esp,	BRESENHAM.SIZE

	; przywróć oryginalne rejestry
	pop	di
	pop	si
	pop	dx
	pop	cx
	pop	bx
	pop	ax

	; powrót z procedury
	ret

1 użytkowników online, w tym zalogowanych: 0, gości: 1