Kreis in Assembler

← Zurück zum Forum

Fujiama ist over, mein Programm abgegeben, Zeit mal wieder für ein "Problem", was ich hier schon längs bearbeiten wollte:

Einen Kreis mit Radius r und den Koordinaten x,y in Assembler berechnen und zeichnen lassen. Sicherlich gibt es hier einige gute Ansätze, die ich gerne mit euch entwickeln bzw. besprechen würde. Es sollte am Ende ein schnelles, kurzes und elegantes Verfahren herauskommen. Dabei würde ich gerne 2 verschiedene Ansätze mit euch entwickeln: Ein Ansatz darf Tabellen hinterlegen und ein anderer Ansatz muss es berechnen ohne Tabellen. Das Ergebnis kommt dann gut aufgearbeitet mit entsprechendem Assembler Code (MADS) und Erklärung ins nächste Magazin...

AntwortZitat

Als kleiner Service 😀 :

KREISE.DOC

=====================================

         Dokumentation zu

            KREISE.SRC

=====================================

Haben Sie schon versucht, Kreise in
BASIC auf den Bildschirm zu zeichen?
Wenn ja, dann wissen Sie, dass man
dabei am besten den Kaffe holt,
Zigarette besorgen geht, oder den
fehlenden Schlaf der letzten am
Computer verbrachten Nacht nachholt.

In Maschinensprache geht natuerlich
alles schneller und besser, warum
soll's mit dem Kreisemalen nicht
genauso sein?

Bevor ein Kreis am Bildschirm er-
scheinen will, muss man gewoehnlich
schon etwas an Mathematik aufbieten.
Entweder strapaziert man die Kreis-
gleichung und kommt dem Kreis mit
Wurzeln auf die Spur, oder man
macht's mit Hilfe von trigono-
metrischen Funktionen, sprich Sinus
und Kosinus.

Jedem Assemblerprogrammierer wird
inzwischen der Mut vergangen sein,
denn mit Wurzeln oder gar einem
Sinus will man sich in Assembler
wirklich nicht herumschlagen.
Schliesslich hat man auch ohne Sinus
schon genug Probleme.


Es geht auch ohne
-----------------

Eine wirklich hochinteressante
Methode zum Zeichnen von Kreisen
habe ich im BASIC XL-TOOLKIT (von
OSS) entdeckt. Damit ist es moeglich,
einen Kreis nur mit Hilfe von
Additionen und Subtraktionen zu
berechnen. Das Pogramm arbeitet mit
einer Naeherungsformel fuer einen
Achtel-Kreisbogen, der ganze Kreis
wird dann durch Spiegelung dieses
Bogens erzeugt.

Am Ende dieses Files finden Sie
das BASIC-Programm als Anhang.

Da ich vor gar nicht zurueckschrecke,
habe ich dieses Programm sogleich
in Assembler umgesetzt, und, Sie
werden es sehen, was herausgekommen
ist tatsaechlich beeindruckend.


High-Speed PLOT
===============

Wuerde man jetzt mit diesem wirklich
schnellen Kreis-Algoritmus die PLOT
Routine des Betriebssystems ver-
wenden, so hiesse das einen Porsche
mit Goggomotor zu fahren.

Nein, hier musste schon eine super-
schnelle PLOT-Routine her. Die finden
Sie in dem UP PLOT, es arbeitet mit
allen Zwei-Farb Graphikmodi (GR.4,6,
8,14) und geht, da es mit Tabellen
arbeitet, recht flott.

Die geplotteten Punkte werden Ex-
klusiv-Oder verknuepft, d.h. wenn Sie
einen Punkt auf ein bereits gesetztes
Pixel plotten, so wird dieses ge-
loescht. Auf diese Art koennen Sie
einen Kreis einfach durch nochmaliges
Zeichnen wieder vom Bildschirm ent-
fernen.


DEMO
====

Im Demo-Programm werden Ihnen die
Faehigkeiten dieser Kreis-Routine
anschaulich gezeigt: Sie koennen
einen Kreis mit dem Joystick ueber
den Bildschirm bewegen. Die Groesse
des Kreises koennen Sie mit dem
Feuerknopf veraendern.

Benutzt wird die Graphikstufe 6,
die die gleiche Aufloesung wie GR.7
besitzt, nur eben mit zwei Farben
arbeitet. Sie koennen auch mal
GR. 14 versuchen, nur bekommen Sie
dann 'Eier' statt Kreise, da die
Pixels nicht mehr quadratisch sind.


Hier noch das Basic-Programm:
-----------------------------

 10 PHI=0:RADIUS=30
 20 MX=79:MY=47
 30 X=RADIUS:Y=0
100 GRAPHICS 6+16:COLOR 1

110 PLOT (MX+X,MY+Y)
130 PLOT (MX-X,MY+Y)

140 PLOT (MX-X,MY-Y)
120 PLOT (MX+X,MY-Y)

150 PLOT (MX+Y,MY+X)
170 PLOT (MX-Y,MY+X)

180 PLOT (MX-Y,MY-X)
160 PLOT (MX+Y,MY-X)

200 PHIY =PHI+Y+Y+1
210 PHIXY=PHIY-X-X+1
220 PHI  =PHIY
230 Y    =Y+1
240 IF ABS(PHIXY)>ABS(PHIY) THEN
    PHI=PHIXY:X=X-1
250 IF Y<=X THEN 110
290 GOTO 290



phi = 0;
y = 0;
x = radius;

mxpx = mx + x;
mxmx = mx - x;
mxpy = mx;
mxmy = mx;

mypy = my;
mymy = my;
mypx = my + x;
mymy = my - x;

do
{
plot (...)

phi = phi + y+y+1;
phixy = phi -x-x+1;

++y;
++mxpy;
--mxmy;
++mypy;
--mymy;


if abs(phixy) > abs(phi) then
   phi = phixy;
   --x;
   ++mxmx;
   --mxpx;
   ++mymx;
   --mypx;

}
while(y<=x)



Die einzelnen Befehle sind im
Assemblerprogramm als Kommentar
angegeben, so dass Sie sich leichter
zurechtfinden.

Noch ein Tip zum Schluss: Interessant
ist dieses Programm auch in GR. 8,
aber dazu reicht der reservierte
Speicherplatz ab $A800 nicht aus.
Waehlen Sie daher mit dem CUSTOMIZER
(Beschreibung siehe CUSTOM.DOC)
den EXTEND-Modus an, aendern Sie
ORG auf $9000 und ZLAENGE auf 40,
den GR.8 hat ja 40 BYTES pro Zeile.
Gestartet wird das PGM dann mit
G9000 im Monitor. Schliesslich koennen
Sie XMAX (achtung, nur bis 255!)und
YMAX noch vergroesern, um mehr
Bewegungsfreiheit zu bekommen.

Sie werden staunen, wie schnell
besonders die kleineren Kreise ueber
den Bildschirm flitzen.
AntwortZitat

KREISE.SRC

***********************************
*          High-Speed Kreise
*
*         in Maschinensprache
***********************************
*
* IOCB-Struktur, CIO-Befehle...
*
ICCOM EQU $342
ICBAL EQU $344
ICBAH EQU $345
ICAX1 EQU $34A
ICAX2 EQU $34B
CIOV  EQU $E456   CIO-Vektor
COPEN EQU   3
CCLSE EQU  12
*
* Betriebssystem-Variable
*
SAVMSC  EQU  $58     Bildschirm-Adresse
STICK0  EQU  $278   Joystick 0
STRIG0  EQU  $284   Trigger  0
*
* Konstante des Demo-Programmes
*
MX  EQU 79      Mittelpunkt X
MY  EQU 47      Mittelpunkt Y
RADMAX  EQU 79      max. Radius
YMAX  EQU 96      Aufloesung vert.
XMAX  EQU 160     Aufloesung hor.
ZLAENGE EQU 20      Bytes pro Zeile
*
* Zeropage-Variable
*
ZEIGER  EQU $D4    Zeropage fuer PLOT
XLAUF EQU $D6     X-Laufvariable
YLAUF EQU $D7     Y-Laufvariable
PHI EQU $D8     Variable fuer
PHIY  EQU $DA     Naeherung
PHIXY EQU $DC
APHIY EQU $DE     Absolutwert PHIY
APHIXY  EQU $E0     Absolutwert PHIXY
MXLAUF  EQU $E2     Laufvariable MP
MYLAUF  EQU $E3
RADIUS  EQU $E4     Laufvariable Radius

  ORG $A800 im res. Bereich

*************************************
* Demo-Programm: Ein beliebig grosser
* Kreis kann mit dem Jostick am
* Schirm bewegt werden.
*************************************
*
* GRAPHICS 6+16
*
START LDA #6+16 GRAPHICS 7,
  JSR GRAPHICS  ganzen Screen
  JSR PLOTAB  Tabellen...
  LDA #MX
  STA MXLAUF
  LDA #MY
  STA MYLAUF
  LDA #45   Vorgabe f.
  STA RADIUS

DEMO  JSR KREIS Kreis zeichen
*
* Joystick oder Knopf aktiv
*
WARTEN  LDA STICK0  Stick 0
  CMP #15   bewegt?
  BNE KRSNEU  ja -->
  LDA STRIG0  Knopf gedr.
  BNE WARTEN  nein--
*
* wenn Joystick bewegt wurde, dann
* zuerst den alten Kreis loeschen
*
KRSNEU  JSR KREIS Kreis loeschen

  LDA STICK0
  AND #8
  BNE LINKS
  INC MXLAUF
  JMP UNTEN
LINKS LDA STICK0
  AND #4
  BNE UNTEN
  DEC MXLAUF
UNTEN LDA STICK0
  AND #2
  BNE OBEN
  INC MYLAUF
  JMP TRIGGER
OBEN  LDA STICK0
  AND #1
  BNE TRIGGER
  DEC MYLAUF
*
* mit dem Feuerknopf kann der Radius
* veraendert werden.
*
TRIGGER LDA STRIG0
  AND #1
  BNE SCHLUSS
  INC RADIUS
  LDA RADIUS
  CMP #RADMAX zu gross?
  BCC SCHLUSS nein-->
  LDA #3    min. Radius
  STA RADIUS
SCHLUSS JMP DEMO

*************************************
* Dieses Unterprogramm zeichnet einen
* Kreis mit:
*
* RADIUS: Radius des Kreises
* MXLAUF: Mittelpunkt X-Koord.
* MYLAUF: Mittelpunkt Y-Koord.
*************************************

KREIS LDA RADIUS
  STA XLAUF
  LDA #0
  STA YLAUF
  STA PHI
  STA PHI+1
*
PIXEL JSR SPIEGEL
  JSR APPROX
*
* Until YLAUF>XLAUF
*
  LDA XLAUF
  CMP YLAUF
  BCS PIXEL
  RTS

*************************************
* Naeherung fuer 1/8-Kreissektor
*************************************
*
* PHIY=PHI+YLAUF+YLAUF+1
*
APPROX  LDA PHI+1
  STA PHIY+1
  CLC
  LDA PHI
  ADC YLAUF
  BCC APRX1
  INC PHIY+1
APRX1 CLC
  ADC YLAUF
  BCC APRX2
  INC PHIY+1
APRX2 STA PHIY
  INC PHIY
  BNE APRX3
  INC PHIY+1
*
* PHIXY=PHIY-XLAUF-XLAUF+1
*
APRX3 LDA PHIY+1
  STA PHIXY+1
  SEC
  LDA PHIY
  SBC XLAUF
  BCS APRX4
  DEC PHIXY+1
APRX4 SEC
  SBC XLAUF
  BCS APRX5
  DEC PHIXY+1
APRX5 STA PHIXY
  INC PHIXY
  BNE APRX6
  INC PHIXY+1
*
* PHI=PHIY
*
APRX6 LDA PHIY
  LDX PHIY+1
  STA PHI
  STX PHI+1
*
* YLAUF=YLAUF+1
*
  INC YLAUF
*
* Absolutwerte von PHIXY und PHIY
*
  LDX #PHIXY
  LDY #APHIXY
  JSR ABSOLUT
  LDX #PHIY
  LDY #APHIY
  JSR ABSOLUT
*
* IF ABS(PHIXY)<ABS(PHIY) THEN
*
  LDA APHIXY+1
  CMP APHIY+1
  BNE APRX7
  LDA APHIXY
  CMP APHIY
APRX7 BCS GRGLCH  ist '>='
*
* PHI=PHIXY:XLAUF=XLAUF-1
*
  LDA PHIXY
  LDX PHIXY+1
  STA PHI
  STX PHI+1
  DEC XLAUF
*
GRGLCH  RTS

************************************
* Acht Spiegelungen des Kreisbogens
* plotten
************************************
*
* PLOT MX+XLAUF, MY+YLAUF
*
SPIEGEL LDA MXLAUF
  CLC
  ADC XLAUF
  TAX
  LDA MYLAUF
  CLC
  ADC YLAUF
  TAY
  JSR PLOT
*
* PLOT MX-XLAUF, MY+YLAUF
*
  LDA MXLAUF
  SEC
  SBC XLAUF
  TAX
  LDA MYLAUF
  CLC
  ADC YLAUF
  TAY
  JSR PLOT
*
* PLOT MX+XLAUF, MY-YLAUF
*
  LDA MXLAUF
  CLC
  ADC XLAUF
  TAX
  LDA MYLAUF
  SEC
  SBC YLAUF
  TAY
  JSR PLOT
*
* PLOT MX-XLAUF, MY-YLAUF
*
  LDA MXLAUF
  SEC
  SBC XLAUF
  TAX
  LDA MYLAUF
  SEC
  SBC YLAUF
  TAY
  JSR PLOT
*
* PLOT MX+YLAUF, MY+XLAUF
*
  LDA MXLAUF
  CLC
  ADC YLAUF
  TAX
  LDA MYLAUF
  CLC
  ADC XLAUF
  TAY
  JSR PLOT
*
* PLOT MX-YLAUF, MY+XLAUF
*
  LDA MXLAUF
  SEC
  SBC YLAUF
  TAX
  LDA MYLAUF
  CLC
  ADC XLAUF
  TAY
  JSR PLOT
*
* PLOT MX+YLAUF, MY-YLAUF
*
  LDA MXLAUF
  CLC
  ADC YLAUF
  TAX
  LDA MYLAUF
  SEC
  SBC XLAUF
  TAY
  JSR PLOT
*
* PLOT MX-YLAUF, MY-YLAUF
*
  LDA MXLAUF
  SEC
  SBC YLAUF
  TAX
  LDA MYLAUF
  SEC
  SBC XLAUF
  TAY
  JSR PLOT
  RTS

*************************************
* Berechnung des Absolutwertes
*                (Betrages)
*
* <X>:Zeiger auf 16-Bit Integer des
*     der umzuwandelnden Zahl
* <Y>:Zeiger auf Ergebnis (ebenfalls
*     16-Bit Int.), beides sind
*     Zeiger in die Zerpage!
*
*************************************

ABSOLUT LDA 1,X   Vorzeichen des MSB    negativ?
  BMI ANEG    negativ->
  STA 1,Y   positive Zahl
  LDA 0,X   Absolutwert ist
  STA 0,Y   die Zahl selbst
  RTS
*
* bei neg. Zahlen: Zahl=0-Zahl
*
ANEG  SEC 
  LDA #0  zuerst das LSB
  SBC 0,X
  STA 0,Y
  LDA #0  und jetzt das MSB
  SBC 1,X
  STA 1,Y
  RTS

*************************************
* GRAPHICS-Unterprogramm
*
* Aufruf: JSR GRAPHICS
*
* PARAMETER:
* <A> 0 bis 15 (XL/XE)
*     0 bis 11 (400/800)
*************************************

GRAPHICS PHA    Graphik-Stufe merken
  LDX #$60    IOCB Nr. 6
  LDA #CCLSE  Screen-IOCB zuerst
  STA ICCOM,X schliessen
  JSR CIOV
  PLA   Graphik-Stufe
  STA ICAX2,X zurueckholen
  AND #$F0    und passende
  EOR #$10    Bit-Kombination
  ORA #$0C    fuer Handler
  STA ICAX1,X herstellen
  LDA #COPEN  jetzt den Befehl
  STA ICCOM,X zum Oeffen des Screens
  LDA #SDEVICE  Zeiger auf Device-
  STA ICBAL,X bezeichnung
  LDA #SDEVICE/256
  STA ICBAH,X
  JMP CIOV
  RTS 

SDEVICE ASC "S:"    Display-Handler

*************************************
* HI-SPEED PLOT fuer Einfarb-Modi
*
* Aufruf: JSR PLOT
*
* PARAMETER:
* <X>,<Y> je nach Graphikstufe
*************************************

PLOT  CPY #YMAX Grenzen
  BCS PLOTEND pruefen
  CPX #XMAX
  BCS PLOTEND
  LDA ADRLO,Y Bildschirm-
  STA ZEIGER  adresse
  LDA ADRHI,Y in Zeropage
  STA ZEIGER+1
  TXA
  LSR   ;geteilt
  LSR   ;durch 8
  LSR
  TAY   ;Index f. X-Pos
  TXA   X-Position
  AND #7
  TAX
  LDA PIXTAB,X  Welches Pixel
  EOR (ZEIGER),Y  und Pixel manipulieren  
  STA (ZEIGER),Y  zurueck in Graphik
PLOTEND RTS

**************************************
* Erzeugt Adresstabellen fuer Plot
*
* muss vor der ersten Verwendung von
* Plot und nach dem GRAPHICS-Befehl
* stehen!
***************************************

PLOTAB  LDA SAVMSC  Anfangsadresse
  STA ZEIGER  des Video-Rams
  LDA SAVMSC+1
  STA ZEIGER+1
  LDY #0    Index auf 0

NXTADR  LDA ZEIGER  Adresstabellen
  STA ADRLO,Y aufbauen
  LDA ZEIGER+1  MSB-Tabelle
  STA ADRHI,Y
  CLC
  LDA ZEIGER  Adresse des
  ADC #ZLAENGE  naechsten Zeilen
  STA ZEIGER  anfangs berechnen
  LDA ZEIGER+1
  ADC #0
  STA ZEIGER+1
  INY
  CPY #YMAX schon f. alle Zeilen?
  BNE NXTADR  nein -->
  RTS
*
* ab hier stehen die Tabellen
*
PIXTAB  DFB 128,64,32,16,8,4,2,1
ADRLO ORG *+YMAX  Platz fuer
ADRHI ORG *+YMAX  Tabellen
AntwortZitat

lieben Dank schon mal.... du bist schnell!! 😉

Den einen Link von dir - vielen Dank - habe ich mir schon mal angeschaut und fand die Basic Version von Slatko Bleha von 1989 echt interessant:

1 REM *******************************
2 REM PROGRAM  : FAST CIRCLE DRAWING
3 REM AUTHOR   : ZLATKO BLEHA
4 REM PUBLISHER: MOJ MIKRO MAGAZINE
5 REM ISSUE NO.: 1989, NO.3, PAGE 29
6 REM *******************************
7 REM 
10 GRAPHICS 8:SETCOLOR 2,0,0:COLOR 3
20 ? "ENTER X, Y AND R"
30 INPUT X,Y,R
40 IF R=0 THEN PLOT X,Y:END 
50 B=R:C=0:A=R-1
60 PLOT X+C,Y+B
70 PLOT X+C,Y-B
80 PLOT X-C,Y-B
90 PLOT X-C,Y+B
100 PLOT X+B,Y+C
110 PLOT X+B,Y-C
120 PLOT X-B,Y-C
130 PLOT X-B,Y+C
140 C=C+1
150 A=A+1-C-C
160 IF A>=0 THEN 190
170 B=B-1
180 A=A+B+B
190 IF B>=C THEN 60

Mit diesen sehr einfachen Befehlen zeichnet man einen Kreis. Keine aufwendigen Berechnungen.... Echt cool!! Ist dein Assembler-Code die Umsetzung dieses Basic Codes??

LG Peter

AntwortZitat