assembler rysowanie koła

1

hej, ten kod ponizej rysuje 8 punktow. Musze je opakowac w petle while, probowalam cos w stylu cmp counter, 0 jne START ale mam taki problem: "jump out of range", czyli za duzo linijek kodu do przeskoczenia. Jak zmniejsze to dostaje infinite loop i bląd "Illegal writing to address". Platforma to DOSBox, MASM assembler
kod

DATA1 segment
P1	DW 0
P2	DW 0
X       DW 0    ; zmienna przechowująca wsp. X 
Y       DW 100    ; zmienna przechowująca wsp. Y 
kolor   DB 0    ; rezerwujemy 1 bajt na  
XC	DW 200
YC	DW 500
DATA1 ends 

CODE1 segment 
ASSUME cs:CODE1, ds:DATA1, ss:STOS1 
point:         
	mov AX,0A000h         
	mov ES,AX      ; do ES segment pamieci ekranu         
	;mov AX, Y
	mov ax, P2
	add ax,Y       
	mov DX,320         
	mul DX         
	;mov dx,X
	mov dx, P1       
	add ax,dx               
	mov di,ax         
	mov AL,kolor   ; do AL=kolor         
	mov ES:[DI],AL ; zapalamy punkt w pamieci obrazu; 
	ret

START: ;inicjalizacja stosu         
	mov ax,seg STOS1         
	mov ss,ax         
	mov sp,offset top ; przelaczenie karty w graficzny tryb 13h         

	mov ah,00h     ; do AH numer funkcji przerwania 10h         
	mov al,13h     ; do AL numer włączanego trybu        
	int 10h         ; włączamy tryb graficzny 13h ; - oczekiwanie na naciśnięcie dowolnego klawisza         

	mov ax,0       ; funkcja 00 przerwania 16h czeka na klawisz         
	int 16h         ; przerwanie obsługujące klawiaturę; ustalamy wsp. punktu i jego kolor...         

	;punkt1
	; Y + XC, X+YC
	mov ax, Y
	add ax, XC
	mov P1, ax
	mov ax, X
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call dupa

	;punkt2
	; X + XC, Y+YC
	mov ax, X
	add ax, XC
	mov P1, ax
	mov ax, Y
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point

	;punkt3
	; -X+XC, Y+YC
	mov ax, 0
	sub ax, X
	add ax, XC
	mov P1, ax
	mov ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point

	;punkt4
	; -Y+XC, X+YC
	mov ax, 0
	sub ax, Y
	add ax, XC
	mov P1, ax
	mov ax, X
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point

	;punkt5
	; -Y + XC, -X+YC
	mov ax, 0
	sub ax, Y
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, X
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point


	;punkt6
	; -X+XC, -Y+YC
	mov ax, 0
	sub ax, X
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point

	;punkt7
	;X+XC, -Y+YC
	mov ax, X
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point

	;punkt8
	;Y+XC, -X+YC
	mov ax, Y
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, X
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call point


	; znow oczekiwanie na naciśnięcie dowolnego klawisza         
	
	mov ax,0                
	int 16h  

; powrot do trybu tekstowego            
	mov ah,00h     ; do AH numer funkcji przerwania 10h         
	mov al,03h     ; do AL numer włączanego trybu
	int 10h
	mov ax, 4c00h
	int 21h

	CODE1 ends

STOS1 segment STACK
	dw 256 dup(?)
top	dw ?
STOS1	ends
END	START
  

jest on oparty na algorytmie napisanym w jezyku wysokiego poziomu. Oto ten (dzialajacy) kod, korzystajacy z programu Processing

void circle(float xc, float yc, float x,float y) {
  point(y+xc,x+yc);
  point(x+xc,y+yc);
  point(-x+xc,y+yc);
  point(-y+xc,x+yc);
  point(-y+xc,-x+yc);
  point(-x+xc,-y+yc);
  point(x+xc,-y+yc);
  point(y+xc, -x+yc);
}

void setup() {
  size(1000,1000);
  //stroke(255,128,0);
  //background(192, 64, 0);
}
void draw() {
float xc=200;
float yc=500;
float r=100;
float x=0;
float y=r;
float d=3-2*r;

while (x!=y) {
  circle(xc,yc,x,y);
  if(d<0) {
    d+=4*x+6;
    x+=1;
    y+=1;
  }
  else {
    d+=4*(x-y)+10;
    x+=1;
    y-=1;
  }
}
}

jak widac funkcja circle to u mnie w assemblerze cała funkcja START. Tylko funkcja 'dupa' jest oddzielna i sluzy do rysowania punktu o wspolrzednych P1, P2. Chce opakowac teraz to START w while, ale nie wiem jak to zrobic

1

Na assemblerze się nie znam, ale dałem łapkę w górę za nazwanie funkcji dupa ;)

0

W sumie to niewiele pamiętam z asma ix86 16bit bo chyba piszesz to w trybie 16bitowym. Tam są pewne ograniczenia co do zakresu skoków. Pod tym linkiem: https://pl.wikibooks.org/wiki/Asembler_x86/Instrukcje/Skokowe#jmp masz podane dlaczego masz błąd zbyt dalekiego skoku (-128/+127).

Możesz spróbować zrobić tak:

 cmp counter,0
 je skip
 jmp start
skip:  tu_dalsza część kodu

Ale tak jak mówię - piszę to z pamięci, po wielu latach poza asm ix86 - nie kompilowałem tego.

0

z problemem zbyt duzego skoku poradzilam sobie refaktorujac ten duzy kawalek kodu w kilka funkcji. Teraz mam inny problem. Program wchodzi w nieskonczoną pętle - maluje kazdy piksel ekranu na bialo, po czym juz nie wychodzi z petli. Nie ma zadnego bledu ani warninga. Dlaczego tak sie dzieje, nie mam pojecia, na moje nie ma tam zadnej nieskonczonej petli, prosze o pomoc bo plakac mi sie chce :( Program zaczyna dzialanie od funkcji START


DATA1 segment
D	DW 3
P1	DW 0
P2	DW 0
X       DW 0    ; zmienna przechowująca wsp. X 
R	DW 100
Y       DW 100    ; zmienna przechowująca wsp. Y 
kolor   DB 0    ; rezerwujemy 1 bajt na  
XC	DW 200
YC	DW 500
DATA1 ends 

CODE1 segment 
ASSUME cs:CODE1, ds:DATA1, ss:STOS1 
drawPoint:         
	mov AX,0A000h         
	mov ES,AX      ; do ES segment pamieci ekranu         
	;mov AX, Y
	mov ax, P2
	add ax,Y       
	mov DX,320         
	mul DX         
	;mov dx,X
	mov dx, P1       
	add ax,dx               
	mov di,ax         
	mov AL,kolor   ; do AL=kolor         
	mov ES:[DI],AL ; zapalamy punkt w pamieci obrazu; 
	ret
punkt1:
	; Y + XC, X+YC
	mov ax, Y
	add ax, XC
	mov P1, ax
	mov ax, X
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	ret
punkt2:
	; X + XC, Y+YC
	mov ax, X
	add ax, XC
	mov P1, ax
	mov ax, Y
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt1
	ret
punkt3:
	; -X+XC, Y+YC
	mov ax, 0
	sub ax, X
	add ax, XC
	mov P1, ax
	mov ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt2
	ret
punkt4:
	; -Y+XC, X+YC
	mov ax, 0
	sub ax, Y
	add ax, XC
	mov P1, ax
	mov ax, X
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt3
	ret
punkt5:
	; -Y + XC, -X+YC
	mov ax, 0
	sub ax, Y
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, X
	add ax, YC
	add P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt4
	ret
punkt6:
	; -X+XC, -Y+YC
	mov ax, 0
	sub ax, X
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt5
	ret
punkt7:
	;X+XC, -Y+YC
	mov ax, X
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, Y
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt6
	ret
punkt8:
	;Y+XC, -X+YC
	mov ax, Y
	add ax, XC
	mov P1, ax
	mov ax, 0
	sub ax, X
	add ax, YC
	mov P2, ax
	mov kolor,15    ;obliczamy odpowiedni adres w pamieci obrazu 
	call drawPoint
	call punkt7
	ret

START: ;inicjalizacja stosu         
	mov ax,seg STOS1         
	mov ss,ax         
	mov sp,offset top ; przelaczenie karty w graficzny tryb 13h         

	mov ah,00h     ; do AH numer funkcji przerwania 10h         
	mov al,13h     ; do AL numer włączanego trybu        
	int 10h         ; włączamy tryb graficzny 13h ; - oczekiwanie na naciśnięcie dowolnego klawisza         

	mov ax,0       ; funkcja 00 przerwania 16h czeka na klawisz         
	int 16h         ; przerwanie obsługujące klawiaturę; ustalamy wsp. punktu i jego kolor...         



	; znow oczekiwanie na naciśnięcie dowolnego klawisza   
	mov bx, R
	add bx,bx
	sub D, bx 
	jmp L1 

IF11:
	mov bx, X
	add bx,bx
	add bx,bx
	add bx,bx
	add bx, 6
	add bx, D
	mov D, bx
	add X,1
	add Y,1
	jmp ENDIF11
ELSE11:
	mov bx, X
	sub bx, Y
	add bx,bx
	add bx,bx
	add bx,bx
	add bx,	10
	add bx, D
	mov D, bx
	add X,1
	sub Y,1
	jmp ENDIF11
	   
L1:
	call punkt8
	cmp D, 0
	jl IF11
	jmp ELSE11
ENDIF11:
	mov bx, Y
	cmp X,bx
	jne L1
	mov ax,0                
	int 16h  

; powrot do trybu tekstowego            
	mov ah,00h     ; do AH numer funkcji przerwania 10h         
	mov al,03h     ; do AL numer włączanego trybu
	int 10h
	mov ax, 4c00h
	int 21h

	CODE1 ends

STOS1 segment STACK
	dw 256 dup(?)
top	dw ?
STOS1	ends
END	START
  
0

Nom, GynvaelColdwind pewnie by to ogarnął, bo robił stream o osdev, ale... Nie za bardzo czaję baze, ale według mnie namieszane jest tutaj coś ze skokami pod etykiety i instrukcjami warunkowymi w tym fargmencie. W START na samym końcu jest jmp L1, skoro rysuje to pierwsza instrukcja call punkt8 jest ok, ale potem jest cmp D, 0 i po nim jakiś skok typu JL - skok, jeśli mniejsze (ze znakiem) do IF11, z którego potem znowu skaczesz do kolejnej etykiety ENDIF11 gdzie sprawdzane jest cmp X, bx i warunek JNE - skok, jeśli nie równe i potem znowu skok pod L1, z której znowu wracasz pod IF11. Nie wiem co tam dzieje się z X i Y po drodze ale dla mnie te skoki wydają się być w kółko tutaj. Może też instrukcje warunkowe jl albo jne są niewłaściwe tutaj. W sumie się nie znam za bardzo, ale to rzuciło mi się w oczy.

    START: ;inicjalizacja stosu         
    mov ax,seg STOS1         
    ...
    jmp L1 
IF11:
    mov bx, X
    ...
    jmp ENDIF11 
ELSE11:
    mov bx, X
    ...
    jmp ENDIF11 

L1:
    call punkt8
    cmp D, 0
    jl IF11
    jmp ELSE11
ENDIF11:
    mov bx, Y
    cmp X,bx
    jne L1
    mov ax,0                
    int 16h 

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