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 🙄

    klick



  • 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 😉


Log in to reply