Halb-Noob in Assembler will voll die tollen intros programmieren, klappt aber nicht.



  • Tja, ich bin vor einer Weile schonmal hier rumgegeistert.
    Jetzt kann ich so ein Bisserl Assemlber und will natürlich, mit meinen nicht ganz so mittelmäßigen Mathe-zum-Anschauen-Kenntnissen, ein paar kleine Demos basteln.
    Also, denk ich mir, "fängste erst mal mit was einfachem an" und bau mir eine Art Funktionsgraph-Darstelldingens. Eigentlich sollten meine zwei Demos eine Linie bzw. einen Kreis (aus Punkten) anzeigen, aber wider erwarten klappt garnix (rien ne va plus - würde ich mit meiner Französisch 5 sagen falls ich Langeweile hätte). Ich hab die beiden .asm Dateien mal hochgeladen, um sie den Blicken euren zahlreichen geschulten Augen auszusetzen.
    Eine weitere Frage: Wie kann ich die verwendete Farbpalette verändern?
    Soviel meinerseits, hier sind die links:
    der Kreis http://collective.valve-erc.com/data/docs/1031593122-87996800/files/fkt.asm
    die Linie http://collective.valve-erc.com/data/docs/1031593122-87996800/files/fputst.asm



  • Hi.

    Dein Kreis-Code war mir ehrlichgesagt zu viel Gewurschtel, also habe ich den nicht naeher korrigiert, aber keine Angst, in deinem Liniencode stecken auch noch Genug Probleme. 😃

    Vielleicht erstmal dazu, wie du den Bildschirmmodus wechselst:
    int 10h erwartet die Funktionsnummer in ah.
    Nun nur al mit dem gewuenschten Grafikmodus zu setzen und dann darauf zu vertrauen, dass ah schon irgendwie 0 (fkt0: Bildschirmmodus wechseln) sein wird ist IMHO unnoetig riskant.

    Nun zu den schwerwiegenderen Fehlern:
    Deine Hauptschleife hat keine Abbruchbedingung => Du hast dir da eine Endlosschleife gebastelt... 🙄
    BTW: Dein Programm wird nach dieser Schleife nicht beendet.

    Wieso speicherst du das Ergebnis der Rechenoperationen auf der FPU bei FS:BX???
    Das waere normalerweise 0000:0000 (fs ist nach Programmstart 0).
    Da liegt der Interrupt-Vector fuer die Exception 0.
    Das zu ueberschreiben ist eher unschoen. 😉
    Also mach dir eine neue Variable und speichere das Ergebnis dann da rein.

    Der 16Bit Integer ist Vorzeichenbehaftet.
    Dh. du hast einen Wertebereich von -32768 bis +32767.
    Das reicht nicht, um den gesamten VGA Bildschirmspeicher zu addressieren.
    Also 2 Moeglichkeiten: Entweder dword nehmen, um das Ergebnis der Rechnungen auf der FPU zu sichern, oder gleich ganz auf dieses gemurxe verzichten (FPU ist allgemein langsamer als Rechenoperationen auf der CPU).

    So, hoffe ich habe jetzt nichts wichtiges uebersehen... 🙄
    Wenn du og. Fehler in beiden Codes beseitigt hast, kann ich mir ja dann den Kreiscode ggf. auch nochmal reinziehen.

    PS: Dir ist klar, dass die Codes selbst auf x86-Ebene noch optimiert werden koennen?



  • Danke! Der Hauptfehler liegt also bei der Vorzeichen Sache.
    Das ganz Geoptimiere lass ich erstmal sein, da ich von Assembler in der Richtung halt nur sehr wenig Ahnung hab. Das mit FS:BX hab ich nur gemacht weil das schneller war als sowas wie FS:0. Die FPU benutze ich heftig weil ich vorhatte mal ein paar chice Sachen in einer .com zu basteln, also Demo-mäßig. Bisher wurschtelte ich sehr viel mit Winamps AVS rum und hab also mathematisch schon ein paar Vorkenntisse.
    Es gibt zwar auch Menschen die die bösesten Sachen nur mit 16bit registern machen können, aber dazu reicht es bei mir noch nicht.
    Also erstmal danke, ich werd das ganze jetzt nochmal überarbeiten und dann nochmal was schreiben.
    Ich werd mich auch noch in Sachen wie assemblern auf welchem prozessor belesen, aber jetzt will ich erstmal dass es bei funzt.
    bis denne.



  • sollte er nicht noch auf tastendruck warten, wenn die cpu mit dem linienzeichnen fertig ist ? sonst sieht er nämlich gar nix, weil das prog gleicht abbricht 🙂

    das geht auch über nen interrupt befehl, frag mich jetz nich wie die fkt nummer heisst.. müsst ich daheim nachgucken..

    oder du programmierst die tastatur von hand..
    in 60h, al
    gibt dir den scancode der taste zurück.
    den müsstest du dir umwandeln is ascii code.. (sofern du den wert in ascii brauchst)
    dazu musst du aber ne eigene tabelle schreiben wo dann die cpu immer nachgucken kann 😉
    der befehl xlatb ist da ganz praktisch.
    darüberhinaus musst du noch bit 7 (letztes bit) vom scancode abfragen, ob taste gedrückt oder losgelassen wurde.. (siehe osdev links in FAQ)

    deshalb:
    auf 16bit ebene reicht der bios-int völlig aus, der gibt gleich den ascii wert zurück..

    mfg



  • hammer schrieb:

    sollte er nicht noch auf tastendruck warten, wenn die cpu mit dem linienzeichnen fertig ist ? sonst sieht er nämlich gar nix, weil das prog gleicht abbricht 🙂

    Joa, auf Tastendruck warten waere vielleicht ganz schoen, ist aber mit Sicherheit nicht notwendig, da man unter Windows sowieso einstellen kann, dass das Fenster nach Beenden offen bleiben soll und DOS ueberpinselt mit seinem Prompt anschliessend nicht die ganze Linie. 😉

    hammer schrieb:

    das geht auch über nen interrupt befehl, frag mich jetz nich wie die fkt nummer heisst.. müsst ich daheim nachgucken..

    Hat zwar keine nach gefragt, es ist aber fkt (ah=) 00h vom int 16h.

    hammer schrieb:

    oder du programmierst die tastatur von hand..
    in 60h, al
    gibt dir den scancode der taste zurück.

    IMHO sollte jeder, der nicht genau weiss, was er da tut, besser Abstand davon nehmen, in Programmen, die veroeffentlicht werden sollen, mehr als unbedingt noetig am Keyboard rumzuschrauben.
    Wenn du zB. einfach so ueber Port 60h Keyboardeingaben ausliest, laeuft dir schon nach kurzer Zeit der Keyboardbuffer ueber.
    Ausserdem ist das richtige Umwandeln des Scancodes in einen ASCII-Code keinesfalls so trivial...

    Dein-Zahnarzt schrieb:

    Das mit FS:BX hab ich nur gemacht weil das schneller war als sowas wie FS:0.

    Und was ist dann bei FS:0 😕
    Ich sehe zumindest in deinen Quellcodes nicht, dass du irgendwo FS initialisierst. Dh. Du kommst auch mit FS:0 wie mit FS:bx bei 0000:0000 raus, und das ist - wie bereits erwaehnt - eher unguenstig. 😉



  • Nobuo T schrieb:

    Nun nur al mit dem gewuenschten Grafikmodus zu setzen und dann darauf zu vertrauen, dass ah schon irgendwie 0 (fkt0: Bildschirmmodus wechseln) sein wird ist IMHO unnoetig riskant.

    Hehe, naja ich wollt halt Speicherplatz sparen 😃 und da ich mich an den sourcecodes anderer dos-demos orientiere, hab ich es so wie fast jeder dort gemacht. (bei 256b kommt der programmierstil meisten zu kurz 🙄 )

    Nobuo T schrieb:

    Deine Hauptschleife hat keine Abbruchbedingung => Du hast dir da eine Endlosschleife gebastelt... 🙄
    BTW: Dein Programm wird nach dieser Schleife nicht beendet.

    Und genau so soll es sein! :p

    Nobuo T schrieb:

    Da liegt der Interrupt-Vector fuer die Exception 0.
    Das zu ueberschreiben ist eher unschoen. 😉

    😕 wenn ich wüsste dass da irgendwas wichtiges rumliegt, hätt' ich wahrscheinlich drauf geachtet. 🤡
    und damit ich es nicht mehr falsch mache, bitte erkläre mir was da mit exception0 und so los ist und vor allem, was genau das heißt.

    Nobuo T schrieb:

    Also mach dir eine neue Variable und speichere das Ergebnis dann da rein.

    extra variable = extra langsam

    Nobuo T schrieb:

    Also 2 Moeglichkeiten: Entweder dword nehmen, um das Ergebnis der Rechnungen auf der FPU zu sichern,

    klappt nicht! 😞

    Nobuo T schrieb:

    oder gleich ganz auf dieses gemurxe verzichten (FPU ist allgemein langsamer als Rechenoperationen auf der CPU).

    so gut bin ich auch noch nicht.
    allein die sinus-berechnung ohne FPU ist riesig.

    Nobuo T schrieb:

    PS: Dir ist klar, dass die Codes selbst auf x86-Ebene noch optimiert werden koennen?

    WTF!? 😮



  • jetzt lasst ihn doch mit dieser ganzen mov al,13h und endlosschleife. so wie ich das verstanden habe versucht er einen effekt zu basteln der in möglichst wenig bytes programmiert wurde und da ist ne tastaturabfrage immer platzaufwendig.

    mein tip: versuch mal les bx,[bx]. das spart dir das push 0a000h pop es.



  • Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Da liegt der Interrupt-Vector fuer die Exception 0.
    Das zu ueberschreiben ist eher unschoen.

    wenn ich wüsste dass da irgendwas wichtiges rumliegt, hätt' ich wahrscheinlich drauf geachtet.
    und damit ich es nicht mehr falsch mache, bitte erkläre mir was da mit exception0 und so los ist und vor allem, was genau das heißt.

    Im RealMode/V86 (in dem dein Programm in DOS nunmal laeuft), liegt bei 0000:0000 die Interrupt-Vector Tabelle. Dh. da liegen die ganzen FAR-Pointer zu den Behandlungsroutinen der Interrupts 0 bis 255.
    Diese Interrupts werden auch fuer die Behandlung von IRQs (Interrupts, die von PC-Perepherie ausgeloest werden) und "schwere Ausnahmefehlern" (um es mit Windows-Sprache auszudruecken 😉 ), bzw. "Exceptions" verwendet.
    Und genau der Int 0 ist nunmal der Handler fuer den "Schweren Ausnahmefehler 0" (Division durch 0).
    Wenn nun ein Programm, das nach deinem gestartet wird, oder dein Programm selbst, den int 0h nicht neu besetzt und nun eine Division durch 0 Fabriziert, bzw. einen Ueberlauf bei der Division, darfst du erstmal die Resettaste druecken, wenn sich der PC nicht selbst neu startet. 😉

    Ist allerdings egal, wenn sich dein Programm eh nicht beendet, obwohl mir immernoch zB. der Stack als gute Alternative zur Interrupt-V. Tabelle einfaellt. 🙄

    Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Also mach dir eine neue Variable und speichere das Ergebnis dann da rein.

    extra variable = extra langsam

    Das musst du mir nun wiederum erklaeren. 😃

    Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Also 2 Moeglichkeiten: Entweder dword nehmen, um das Ergebnis der Rechnungen auf der FPU zu sichern,

    klappt nicht!

    Komisch, bei mir schon (Nur um Misverstaendnissen vorzubeugen: ich habe nur den Code in fputst.asm bearbeitet). :p

    Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    oder gleich ganz auf dieses gemurxe verzichten (FPU ist allgemein langsamer als Rechenoperationen auf der CPU).

    so gut bin ich auch noch nicht.
    allein die sinus-berechnung ohne FPU ist riesig.

    Gut, das mag sein, aber in fputst.asm ist das einfach mal komplett unnoetig.
    BTW: Fuer Kreise Zeichnen ohne FPU, Sinus etc. gibt es immernoch einen schoenen Bresenham-Algo. => Google.

    @wasily: Kleine Programme schreiben ist ja ganz schoen, aber doch nicht auf Kosten der Funktionalitaet. 😮
    Sry, aber ich kann es einfach nicht fuer sinnvoll erachten, ein Programm zu schreiben, dass, wenn es nicht in einem Sandkasten gestartet wird, den Rechner aufhaengt, nur um letztendlich vielleicht 10Byte zu sparen. 🙄





  • Ach, sag nur! 😮
    Heisst aber noch lange nicht, dass ich solche bis aufs letzte und mit hoechst dubiosen Praktiken zusammengestauchten Teile gut finden/heissen muss, oder? 😉



  • ne =p



  • IMHO sollte jeder, der nicht genau weiss, was er da tut, besser Abstand davon nehmen, in Programmen, die veroeffentlicht werden sollen, mehr als unbedingt noetig am Keyboard rumzuschrauben.
    Wenn du zB. einfach so ueber Port 60h Keyboardeingaben ausliest, laeuft dir schon nach kurzer Zeit der Keyboardbuffer ueber.

    also bei meinem 32bit kernel läuft das mit hilfe eines ISR ganz gut 😃
    klar, ein kbreset sollte noch rein.
    aber wenn er ein programm schreiben will, das unter windows/dos laufen soll,
    hast du recht, ist es unsinn ueberhaupt die tastatur so von hand anzusteuern.

    Ausserdem ist das richtige Umwandeln des Scancodes in einen ASCII-Code keinesfalls so trivial...

    richtig 😉 bei mir gehen auch nur die normalen kleinen buchstaben.
    große buchstaben mit hilfe der shift-taste hab ich noch net gemacht.
    wenn ich die shift taste druecke oder die entf taste, hab ich so gemacht dass er einfach nen dos smily anzeigt :p

    mfg



  • Nobuo T schrieb:

    Im RealMode/V86 (in dem dein Programm in DOS nunmal laeuft), liegt bei 0000:0000 die Interrupt-Vector Tabelle. Dh. da liegen die ganzen FAR-Pointer zu den Behandlungsroutinen der Interrupts 0 bis 255.
    Diese Interrupts werden auch fuer die Behandlung von IRQs (Interrupts, die von PC-Perepherie ausgeloest werden) und "schwere Ausnahmefehlern" (um es mit Windows-Sprache auszudruecken 😉 ), bzw. "Exceptions" verwendet.
    Und genau der Int 0 ist nunmal der Handler fuer den "Schweren Ausnahmefehler 0" (Division durch 0).
    Wenn nun ein Programm, das nach deinem gestartet wird, oder dein Programm selbst, den int 0h nicht neu besetzt und nun eine Division durch 0 Fabriziert, bzw. einen Ueberlauf bei der Division, darfst du erstmal die Resettaste druecken, wenn sich der PC nicht selbst neu startet.

    Ist allerdings egal, wenn sich dein Programm eh nicht beendet, obwohl mir immernoch zB. der Stack als gute Alternative zur Interrupt-V. Tabelle einfaellt. 🙄

    ach! na wenn weiter nichts ist. 😃
    danke dass du das gesagt hast.

    Nobuo T schrieb:

    Das musst du mir nun wiederum erklaeren. 😃

    probier's aus. register/stack zu benutzen ist immer schneller als extra variablen anzulegen. für solche demos ist es also am besten gar keine variblen zu benutzen. ich bin aber erstmal nur drauf aus dass überhaupt das passiert was ich mir erhoffe.

    Nobuo T schrieb:

    Komisch, bei mir schon (Nur um Misverstaendnissen vorzubeugen: ich habe nur den Code in fputst.asm bearbeitet). :p

    ich auch. ich hab "xpos" und "ypos" in dwords geschrieben, aber das änderte nichts.

    Nobuo T schrieb:

    Gut, das mag sein, aber in fputst.asm ist das einfach mal komplett unnoetig.
    BTW: Fuer Kreise Zeichnen ohne FPU, Sinus etc. gibt es immernoch einen schoenen Bresenham-Algo. => Google.

    hm, nach dem was ich grad in 5 minuten gesehen hab benutzt man den um, mit möglichst wenig rechenaufwand, eine linie zu zeichnen. naja ich hab erstmal alles runtergeladen was hilfreich aussah. ich hab ja ein ganzes wochenende zeit um mich damit zu beschäftigen. 🤡

    Nobuo T schrieb:

    Sry, aber ich kann es einfach nicht fuer sinnvoll erachten, ein Programm zu schreiben, dass, wenn es nicht in einem Sandkasten gestartet wird, den Rechner aufhaengt, nur um letztendlich vielleicht 10Byte zu sparen. 🙄

    naja es gibt combos auf denen es ziel ist, eine ganz genau 256 bytes große demo mit möglichst beeindruckenden effekten zu basteln. funktional soll sowas nicht unbedingt sein :p hauptsache klein, viel, schnell und möglichst nicht nur auf dem eigenen rechner lauffähig.

    noch eine frage:
    für normale register gibt es "mul" und "imul" eines behandelt ein word als natürliche zahl das andere mit vorzeichen.
    für den fpu gibt es "fmul" welches multiplikation mit rationalen zahlen durchführt und "fimul" welches ganzzahlen verwendet. gibt es da nicht auch sowas wie "hey, das ding hat kein vorzeichen sondern geht von 0 bis 65536"?
    ach ja www.256b.com kenn ich auch. was es da gibt ist echt der hammer!
    raytracing, echte schatten, metapartikel ohne FPU und all das ich höchstens 256 bytes. das will ich auch können! 😋
    die äußerst krassen jungs von farb-rausch haben sogar eine 5byte demo:
    http://www.farb-rausch.com/inyourface.zip
    btw, nobou du solltest besser nicht auf den source code gucken, denn diese demo verursacht einfach nur einen fehler 😃 wodurch dann das gesehene passiert.



  • Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Das musst du mir nun wiederum erklaeren. 😃

    probier's aus. register/stack zu benutzen ist immer schneller als extra variablen anzulegen.

    Register kann ich dir zustimmen - sicher, Speichercycles brauchen laenger Zeit, vorallem, wenn das Zeug nicht gecached ist.
    Stack sind aber auch letztendlich Speicherzugriffe...
    BTW, Was ich eigentlich meinte:
    Wieso sollte der Code langsamer sein, wenn du in eine uninitialisierte Variable im Datensegment (DS) deines Programms schreibst, anstatt mit einem Segment Override irgendwo in der IVT rumzuschreiben?

    Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Komisch, bei mir schon (Nur um Misverstaendnissen vorzubeugen: ich habe nur den Code in fputst.asm bearbeitet). :p

    ich auch. ich hab "xpos" und "ypos" in dwords geschrieben, aber das änderte nichts.

    Wenn es im Ergebnis der Rechnung einen Ueberlauf gibt, macht es irgendwie nicht so besonders viel Sinn, die breite der og. Parameter zu vergroessern, und das Ergebnis zu lassen, wie es ist... 😕

    Dein-Zahnarzt schrieb:

    Nobuo T schrieb:

    Gut, das mag sein, aber in fputst.asm ist das einfach mal komplett unnoetig.
    BTW: Fuer Kreise Zeichnen ohne FPU, Sinus etc. gibt es immernoch einen schoenen Bresenham-Algo. => Google.

    hm, nach dem was ich grad in 5 minuten gesehen hab benutzt man den um, mit möglichst wenig rechenaufwand, eine linie zu zeichnen.

    Jo, der gute Mann hat nicht nur einen Algo fuers Zeichnen von Kreisen ausgehackt, sondern eben auch den von dir offensichtlich ausgegrabenen Algo fuer Linien.

    Dein-Zahnarzt schrieb:

    noch eine frage:
    für normale register gibt es "mul" und "imul" eines behandelt ein word als natürliche zahl das andere mit vorzeichen.
    für den fpu gibt es "fmul" welches multiplikation mit rationalen zahlen durchführt und "fimul" welches ganzzahlen verwendet. gibt es da nicht auch sowas wie "hey, das ding hat kein vorzeichen sondern geht von 0 bis 65536"?

    AFAIK nicht.



  • Nobuo T schrieb:

    probier's aus. register/stack zu benutzen ist immer schneller als extra variablen anzulegen.

    Register kann ich dir zustimmen - sicher, Speichercycles brauchen laenger Zeit, vorallem, wenn das Zeug nicht gecached ist.
    Stack sind aber auch letztendlich Speicherzugriffe...
    BTW, Was ich eigentlich meinte:
    Wieso sollte der Code langsamer sein, wenn du in eine uninitialisierte Variable im Datensegment (DS) deines Programms schreibst, anstatt mit einem Segment Override irgendwo in der IVT rumzuschreiben?[/quote]
    nochmal:
    ich <-- halbnoob 😃 => ich <-- check nix davon 😮 => ich <-- braucht anschauliche erklärung 🙄



  • Ah, I see... 😃
    Haette man auch bei genauerem Studium aus dem Verlauf der Diskussion schliessen koennen, aber gut:

    Ich schrieb in Bezug auf diese Zeile "fist word [FS:BX]":

    Also mach dir eine neue Variable und speichere das Ergebnis dann da rein.

    Darauf du:

    extra variable = extra langsam

    Darauf ich => haeh??
    und Du

    probier's aus. register/stack zu benutzen ist immer schneller als extra variablen anzulegen.

    Diese Aussage zeigte mir, dass du anscheinend meinen Hinweis (quote 1), falsch verstanden hast.

    Also nochmal: Du verwendest bei oben angesprochener Zeile praktisch auch eine "Variable" im Speicher - nur eben an Adresse FS:BX, statt im Segment deines Programms.
    Und genau darauf bezog sich nun meine Frage:
    Warum meinst du, dass ein Zugriff auf FS:BX schneller waere, als zB. ein Zugriff auf ds:MeineVariable oder meinetwegen auch ss:bp?
    Denn genau das impliziert IMHO deine Aussage mit "extra variable = extra langsam".

    Ach ja, bevor noch eine Frage nach der genauen Loesung des Problems mit dem Ueberlauf bei deiner Integer Rechenoperation kommt:
    Du musst bei dem "fist" eine dword-Adresse angeben. :p



  • Dein-Zahnarzt schrieb:

    die äußerst krassen jungs von farb-rausch haben sogar eine 5byte demo:
    http://www.farb-rausch.com/inyourface.zip

    Soll das Teil auch irgendwas cooles machen oder einfach nur Scheiße auf den Schirm spucken...?!?



  • Sgt. Nukem schrieb:

    Soll das Teil auch irgendwas cooles machen oder einfach nur Scheiße auf den Schirm spucken...?!?

    nun ja. es sind fünf byte. sprich 2 oder 3 befehle. damit macht es töne und tolle schrift. ich finde das bemerkenswert.

    ich hab diese pixelmalproggi mal ohne fpu gemacht und es geht.
    http://collective.valve-erc.com/data/docs/1031593122-87996800/files/drawpoints.asm

    schuhu, ich hab ein XORmuster gemacht. nicht neues aber ich habs allein gemacht *stolzsei*
    http://collective.valve-erc.com/data/docs/1031593122-87996800/files/grayxor.asm
    http://collective.valve-erc.com/data/docs/1031593122-87996800/files/xor.asm

    xor.asm macht das was ich eigentlich wollt, einen farbverlauft quer über das bild.

    bleibt die frabe offen, warum das mit der fpu nicht ging. kann mir das jemand erklären. ich dächte ich hab mit der fpu haargenau das gleiche gemacht.



  • Dein-Zahnarzt schrieb:

    Sgt. Nukem schrieb:

    Soll das Teil auch irgendwas cooles machen oder einfach nur Scheiße auf den Schirm spucken...?!?

    nun ja. es sind fünf byte. sprich 2 oder 3 befehle. damit macht es töne und tolle schrift. ich finde das bemerkenswert.

    Ja, gut, stimmt schon... 🙂 👍

    Trotzdem gefallen mir da TGGC's 4K-Demos besser... 🤡 😋



  • du kannst übrigens bytes sparen wenn du statt der überprüfung von X < 320 und Y < 200 einfach ein register als index auf den bildschirmspeicher nimmst und diesen ständig incrementierst. um jetzt die x und y coordinate für deine berechnungen zu bekommen brauchst du nur den indexwert durch 320 zu teilen. das ganzzahlige ergebnis ist der y wert und der rest ist der x wert. du brauchst auch nicht zu überprüfen ob 63999 überschritten wurde da der bildschirmspeicher im modus 13h volle 64k beträgt und wenn das register überläuft dann fängt das programm automatisch wieder bei 0 an.


Anmelden zum Antworten