assembler rysowanie koła

lambdadziara
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 9 godzin
  • Postów:442
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

Kopiuj
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

Kopiuj
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

edytowany 1x, ostatnio: lambdadziara
cerrato
Moderator Kariera
  • Rejestracja:około 7 lat
  • Ostatnio:dzień
  • Lokalizacja:Poznań
  • Postów:8802
1

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


Zobacz pozostałe 4 komentarze
Silv
@vpiotr: już lepsze "funkcja1"...
Silv
PS. @lambdadziara: a w związku z tym przeznaczeniem to oczywiście lepsze bardziej konkretne nazwy niż "funkcja1".
lambdadziara
spokojnie, już zmieniłam
Silv
@lambdadziara: OK, fajnie. ;) Nie chciałbym, żeby było, że się (za bardzo) czepiam, z tym podkreśleniem to w pewnej mierze żart.
vpiotr
Nazwa "point" tez taka sobie. Uzywaj czasownikow dla funkcji (procedur).
VT
  • Rejestracja:ponad 5 lat
  • Ostatnio:prawie 2 lata
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:

Kopiuj
 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.

edytowany 1x, ostatnio: vtx
lambdadziara
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 9 godzin
  • Postów:442
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

Kopiuj

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
  
GO
  • Rejestracja:prawie 6 lat
  • Ostatnio:około 5 lat
  • Postów:97
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.

Kopiuj
    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 

lambdadziara
inkrementuje X i Y w ifie, inkrementuje X dekremtuje Y w else. W obliczaniu wspolrzednych punktow korzystam ze zmiennych pomocniczych P1, P2 aby nie nadpisywac X i Y. Wreszcie X!=Y i to jest koniec petli while (petli L1), to samo jest w kodzie high level Processing.exe w pierwszym poscie

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.