assembler rysowanie koła

Odpowiedz Nowy wątek
2019-10-30 22:56
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

edytowany 1x, ostatnio: lambdadziara, 2019-10-30 23:35

Pozostało 580 znaków

2019-10-30 23:08
1

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


That game of life is hard to play
I'm gonna lose it anyway
The losing card I'll someday lay
So this is all I have to say
Pokaż pozostałe 4 komentarze
@vpiotr: już lepsze "funkcja1"... - Silv 2019-10-30 23:33
PS. @lambdadziara: a w związku z tym przeznaczeniem to oczywiście lepsze bardziej konkretne nazwy niż "funkcja1". - Silv 2019-10-30 23:35
spokojnie, już zmieniłam - lambdadziara 2019-10-30 23:35
@lambdadziara: OK, fajnie. ;) Nie chciałbym, żeby było, że się (za bardzo) czepiam, z tym podkreśleniem to w pewnej mierze żart. - Silv 2019-10-30 23:36
Nazwa "point" tez taka sobie. Uzywaj czasownikow dla funkcji (procedur). - vpiotr 2019-10-31 07:06

Pozostało 580 znaków

2019-10-31 07:45
vtx
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[...]er_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.

edytowany 1x, ostatnio: vtx, 2019-10-31 07:46

Pozostało 580 znaków

2019-11-03 18:46
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

Pozostało 580 znaków

2019-11-03 21:31
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 
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 - lambdadziara 2019-11-03 21:58

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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