Haus vom Nikolaus
-
Hi, wir haben ein fertigen Programmcode bekommen, den wir so ändern sollen das der ein Haus vom Nikolaus malt. Hab da selber bisschen probiert und komischerweise kamen da anstatt einer gleich Dutzend Linien, manchmal auch kreuz und quer, einmal hatte ich es geschafft eine Linie zu malen, aber die war leider von oben nach unten gemalt, aber das Haus vom Nikolaus muss immer unten anfangen, sonnst kann man es nicht in einem Zug malen.
Hier der Programmcode:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Programm zur Ausgabe von Linien im Grafikmodus ; Programmbeginn: Datenzugriff vorbereiten, zum Programmcode springen org 100h mov AX,CS mov DS,AX jmp start ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Daten definieren ; Anfangstext moin db 'Moin',13,10,'$' ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Hauptprogramm start: ; Moin ausgeben mov DX,moin mov AH,9 ; DOS-Fkt: Zeichenkette ausgeben int 21h ; Aufruf DOS ; auf Eingabe einer Taste warten call lieszeichen ; Grafikmodus setzen mov AH,0h ; VGA-Fkt: Grafikmodus setzen mov AL,12h ; VGA-Grafik-Modus 640x480 16 Farben int 10h ; Aufruf Video-BIOS mov AH,0Bh ; VGA-Fkt: Rahmen/Hintergrundfarbe mov BX,1 ; blau int 10h ; Aufruf Video-BIOS ; Linie zeichnen mov [z_beg],word 10 ; Beginn der Linie in Zeile 10 mov word [s_beg],10 ; Beginn der Linie in Spalte 10 mov word [z_end],100 ; Ende der Linie in Zeile 100 mov word [s_end],100 ; Ende der Linie in Spalte 100 call linie ; auf Eingabe einer Taste warten call lieszeichen ; VGA-Mode wieder auf Text setzen mov AH,0h ; VGA-Fkt: Grafikmodus setzen mov AL,03h ; VGA-Text-Modus 80x25 int 10h ; Aufruf Video-BIOS ; Programm beenden mov AH,4Ch ; DOS-Fkt: Programm beenden int 21h ; Aufruf DOS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Unterprogramme ; Unterprogramm Lesen eines Zeichens ; Parameter: keine lieszeichen: mov AH,6 ; DOS-Fkt: Zeichen lesen mov DL,0FFh ; ... ohne Warten int 21h ; Aufruf DOS jz lieszeichen ret ; Unterprogramm Zeichnen einer Linie ; Parameter: folgende Variablen: s_beg dw 0 ; Anfangsspalte s_end dw 0 ; Endspalte z_beg dw 0 ; Anfangszeile z_end dw 0 ; Endzeile linie: ; Lade Koordinaten des Anfangspunkts in Register mov DX,[z_beg] mov CX,[s_beg] ; Schreibe einen Punkt zeichne: mov AH,0Ch ; VGA-Fkt: Grafikpunkt schreiben ; DX = Bildschirmzeile ; CX = Bildschirmspalte ; AL = Farbe mov AL,2 ; grün int 10h ; Aufruf Video-BIOS ; Benutze AL als Flag: 0 'stop', 1 'weiter' mov AL,0 ; initialisiere Flag auf 'stop' cmp CX,[s_end] ; vergleiche aktuelle Spalte mit End-Spalte jz zeile ; wenn gleich, springe ... add CX,1 ; erhöhe Spalte mov AL,1 ; setze Flag auf 'weiter' zeile: cmp DX,[z_end] ; vergleiche aktuelle Zeile mit End-Zeile jz spalte ; wenn gleich, springe ... add DX,1 ; erhöhe Zeile mov AL,1 ; setze Flag auf 'weiter' spalte: cmp AL,1 ; weiter? jz zeichne ; dann springe zu 'zeichne' ret ; Rückkehr zum aufrufenden Programm ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Ende des Programmcodes end
Hoffe ihr könnt mir sagen worauf ich achten soll, oder mir ein, zwei Striche vormalen damit ich mich orientieren kann.
mfg Schmii
-
Es wird doch schon 'ne Linie gezeichnet, naemlich hier:
; Linie zeichnen mov [z_beg],word 10 ; Beginn der Linie in Zeile 10 mov word [s_beg],10 ; Beginn der Linie in Spalte 10 mov word [z_end],100 ; Ende der Linie in Zeile 100 mov word [s_end],100 ; Ende der Linie in Spalte 100 call linie
Jetzt ueberlegst Du Dir die Koordinaten des Hauses und zeichnest 8 Linien.
-
Ja genau, das weiß ich, da hab ich es halt Versucht die Koordinaten anzupassen, aber da kam wie beschrieben meistens nur wirres Zeug bei raus.
-
Zum Beispiel wenn ich das so mache, malt der vom oberen Rand zum unteren fünf parallel Linien auf den Bildschirm und ich versteh nicht wieso.
; Linie zeichnen mov [z_beg],word 200 ; Beginn der Linie in Zeile 10 mov word [s_beg],200 ; Beginn der Linie in Spalte 10 mov word [z_end],100 ; Ende der Linie in Zeile 100 mov word [s_end],200 ; Ende der Linie in Spalte 100 call linie
-
vermutlich weil die funktion zum linien zeichnen nicht mit negativen steigungen umgehen kann.
schmii schrieb:
; Linie zeichnen mov [z_beg],word 200 ; Beginn der Linie in Zeile 10 mov word [s_beg],200 ; Beginn der Linie in Spalte 10 mov word [z_end],100 ; Ende der Linie in Zeile 100 mov word [s_end],200 ; Ende der Linie in Spalte 100 call linie
vertausch hier mal z_beg und z_end.
-
Also das mit dem Vertauschen hat bisher ganz gut geklappt, jedenfalls hab ich nur noch ein Problem. 6 von 8 Linien wurden richtig gezeichnet, aber die beiden Linien die von oben-rechts nach unten-links gehen tanzen etwas aus der reihe, also zB: Das Dach, die rechte Schräge ist richtig aber die linke sieht aus wie die rechte nur das sie um 50 Pixel nach links verschoben ist. Die andere Schräge die halt das Kreuz in der Mitte des Hauses machen sollte, liegt genau über der ersten Schräge.
Das sieht in etwas so aus klick!
-
...ist klar. Die Funktion "linie" kann entweder eine Linie von oben nach unten oder von links nach rechts zeichnen (oder beides kombiniert eine 45°-Linie). Nichts anderes. Falls es zur Aufgabe gehoerte, die Funktion zum Linienzeichnen zu schreiben, wuerde ich vorschlagen, du denkst mal darueber nach, wie signed und unsigned integer in Assembler funktionieren (um die Sache frei in der Richtung zu machen) und schaust dir mal den entsprechenden Bresenham-Algo zum Linien zeichnen an. Ist eigentlich recht naheliegend, aber man muss ja erstmal drauf kommen.
Dann kannst du die Funktion nochmal neu schreiben und zwar so, dass gerade Linien zwischen zwei beliebigen Punkten gezeichnet werden koennen.Edit: Dein verlinktes Bild wird bei mir uebrigens nicht angezeigt - nur Werbung und ein paar weitere Links.
edit: Richtung korrigiert
-
Nobuo T schrieb:
Edit: Dein verlinktes Bild wird bei mir uebrigens nicht angezeigt - nur Werbung und ein paar weitere Links.
das problem habe ich auch seit kurzem bei imageshack. versuch mal die seite neu zu laden, bei mir kommt das bild dann.
-
Noe, nix. Nur jedes mal eine andere Werbung.
-
@Nobuo T, also bei mir ging das mit dem aktualisieren, wenn du willst kann ich das noch mal auf eine andere Seite laden, kenn aber gerade keine
Mit der Bresenham-Algo hab ich mal gegoogelt und hier im Forum geguckt, und das scheint mir für Kreise zu sein oder?
Und das mit der Funktion neuschreiben wird glaube nix, der Lehrer meinte es wird nur mit nem Trick gehen und 45° meinte er auch das das so ok ist.
Und der wichtigste Punkt, wir haben vor 2Wochen erst mit Assembler angefangen und ich blick da eh nicht so durch, das meiste was ich jetzt geschafft hab war nur durch versuchen
-
schmii schrieb:
Mit der Bresenham-Algo hab ich mal gegoogelt und hier im Forum geguckt, und das scheint mir für Kreise zu sein oder?
wikipedia http://de.wikipedia.org/wiki/Bresenham-Algorithmus schreibt, das würde irgendwie auch für geraden gehen.
-
Tja, ohne die Funktion zu modifizieren, faellt mir leider auch kein wirklich toller Trick ein, wie man eine Linie schraeg/von rechts nach links zeichnen kann.
-
Komisch, den Wikipedia Eintrag hat ich nicht gefunden.
@Nobuo T, auf welchen Abschnitt sollte ich mich konzentrieren? Weil ich gerad gar keine Ahnung hab wo ich da suchen soll. Ich hoffe nur nicht ich muss dann das halbe Programm umschreiben
Achja hab noch nen anderen Imagehoster gefunden, hier der neue Link, zum alten Bild
-
Beliebige Steigungen brauchst Du ja nicht, also koenntest Du erstmal sowas versuchen:
cmp CX,[s_end] ; vergleiche aktuelle Spalte mit End-Spalte jz zeile ; wenn gleich, springe ... if cx < [s_end] ; aktuelle spalte kleiner als zielspalte? add CX,1 ; erhöhe Spalte else sub CX,1 ; verringere Spalte zeile: ...
Entsprechend fuer die Zeilen.
Fuehrt dazu dass Du weiterhin nur Geraden mit 0, 45 oder 90 Grad Steigung zeichnen kannst aber dafuer mit beliebigem Vorzeichen (und Reihenfolge der Start/Endkoordinaten).
-
function Line(x0,y0,x1,y1) { if(abs(x0-x1)<=1 && abs(y0-y1)<=1) { Pixel(x0,x1); Pixel(y0,y1); } else { Line((x0+y1)/2,(y0+y1)/2,x0,y0); //beachte: /2 ist wie >>1, shr ax,1 ;) Line((x0+y1)/2,(y0+y1)/2,x1,y1); } }
nicht schnell, primitiv, aber wunderbar einfach, auch in assembler, und fuer ein haus auch voll ausreichend, jetzt musst du den pseudocode nur noch in assembler schreiben