FOR-Schleife nach Z80

  • Guck dir den JR NZ - Befehl an.
    LD BC,5000
    loop: DEC BC
    JR NZ loop:

  • Guck dir den JR NZ - Befehl an.
    LD BC,5000
    loop: DEC BC
    JR NZ loop:


    Danke. Leider hab ich mich etwas unklar Ausgedrückt. Wenn ich das in Assembler nutze, dann rennt es mit Assembler-Speed.
    Wie kann ich aber meine Schleife aus BASIC in Z80 nachbauen, so das beide die gleiche Zeit benötigen?

  • Soweit ich das im Kopf habe, funzt das nicht, da DEC BC nicht Z beeinflusst.
    Korrekt müsste sein:
    LD BC,$irgendwas
    loop:
    DEC BC
    ld A,B
    OR C
    JR NZ,loop



    Bei 8-Bit-werten empfiehlt sich auch DJNZ (da wird B als Zähler genommen). Beispiel:


    LD B,255
    loop:
    ...mache irgendwas...
    DJNZ loop


    BASIC-Timing... schwer. Entweder du bastelst Da NOPs rein (oder CALL $BD19 ;) ), oder machst Doppelschleifen in Form von


    LD HL,wert1
    schleife1:
    LD BC,wert2
    schleife2:
    DEC BC
    LD A,B
    OR C
    JR NZ,schleife2
    DEC HL
    LD A,H
    OR L
    JR NZ,schleife1

  • Hach wenn ich das als Informatiker sehe, dreht sich immer mein Magen um....


    Wenn Du eine Warteschleife / ein Delay brauchst, kommt es auch auf den Rechner an. Also z.B. ob Du an einen Timer rankommst/die Hardware einen Timer-Baustein hat, oder ob Du - noch viel besser - einen Interrupt benutzen kannst, und eine Echtzeituhr a la DALLAS Chip im Rechner hast. Denn eine reine Schleife (oder eine Schleife in einer Schleife) ist abhängig von der Taktfrequenz des Rechners und es lässt den armen Prozessor umsonst herumeiern und Energie verbraten.


    Oder in Kurzform: Am Einfachsten ist natürlich eine Schleife mit zeitfressenden Opcodes (oder eine Schleife in einer Schleife) laufen zu lassen, aber elegant und energiebewusst ist was anderes ;-)


    Gruss Peter

    "Ich habe keine Zeit mich zu beeilen." (Igor Strawinsky)


    ... und schaut auch mal bei meinem Blog vorbei ...

  • Stimmt natürlich.


    Da es aber nur einen 4 MHz-CPC gibt, einTimer in dem Sinne auch nicht vorhanden ist, bleibt nichts anderes übrig.
    Und extra für eine Schleife einen Interrupt einklinken ist dann doch etwas übertrieben :-D

  • Hach wenn ich das als Informatiker sehe, dreht sich immer mein Magen um....


    Hast ja Recht. Aber bei einer 8-Bit 4Mhz Maschine ist es egal. Hauptsache die Zeit vergeht in einer Schleife.


    Hab im Web das gefunden:


    Code
    Z80 5seconds Timer for 10 MHz ORG 0000H LD SP,0FFFFH MAIN: CALL TIMER5TIMER5:LD E,35HJ60: LD B,0FFHJ61: LD D,0FFHJ62: DEC D JP NZ,J62 DEC B JP NZ,J61 DEC E JP NZ,J60 RET END



    Aber noch nicht ausprobiert.

  • energiebewusst


    Das Argument liest man selten bei der Diskussion um Warteschleifenprogrammierung.


    Wenn man allein bedenkt, was man mit den ganzen verschwendeten Prozessortakten anstellen könnte. Von "Taktgefühl spenden bis hin zu BASIC-Programmierern mal ein paar Takte erzählen!


    :prof:

  • Jemand ne Idee, wie man...


    Code
    for a=1 to 5000:next


    als reine Warteschleife in Assembler am besten Nachbauen kann?



    Aus Zaks_Programmierung_des_Z80_ :prof:

  • Wahrscheinlich denke ich so, weil ich vor einiger Zeit Windows-Programme geschrieben habe - dort verschwenderisch mit der Ressource CPU umzugehen, verbietet sich halt, weil das System nicht nur für einen Thread zuständig ist.
    Man erzeugt so unnötig Last in einem Multitasking Betriebssystem. Klar, haben wir hier nicht - ein Z80 ist früheste Steinzeit im Vergleich, da braucht man nicht aufzupassen, eine CPU, eine Task.


    Das Argument "Energie verschwenden" finde ich heutzutage bei Systemen inzwischen auch sehr wichtig, wenn man alleine bedenkt wieviel Energie Google verbraucht, wird's einem richtig schlecht... 2,26 Milliarden Kilowattstunden ist kein Pappenstiel.

    "Ich habe keine Zeit mich zu beeilen." (Igor Strawinsky)


    ... und schaut auch mal bei meinem Blog vorbei ...

  • Ich hab mal ein DOS-Programm unter Windows 95 benutzt. Das war ähnlich programmiert.
    Um rechts unten eine Uhr anzuzeigen, wurde einfach solange Zeit verbraten, bis endlich
    so eine ewige Sekunde umgesprungen ist. Wenn der Benutzer grad nichts gemacht am
    Programm, war das ganz schön anstrengend für die CPU. Blöd war halt, dass das zu 100%
    CPU-Auslastung führt und Windows sich kaum mehr bedienen ließ.
    Ich hab zwar keine Ahnung von CPC-Programmierung, aber unter DOS konnte man sich
    ganz leicht in den Timer-Interrupt reinhängen und den so für Delays nutzen.

  • Soweit ich das im Kopf habe, funzt das nicht, da DEC BC nicht Z beeinflusst.


    Ups, hab schon zu lange nicht mehr Z80 programmiert...


    "Energie sparen" - naja, bei einem Z80 dürfte sich der Stromverbrauch kaum ändern, ob der jetzt alle 4 Taktzyklen einen NOP ausführt oder was rechnet...
    Und natürlich, auf einem CPC mit garantiert 4 MHz Taktfrequenz funzt so eine Schleife sicher und ist am einfachsten programmiert.
    Man muss natürlich bedenken, dass bei anderen Vorraussetzungen, z.B. Portierung des Programms auf ein anderes Z80-System, was dann z.B. mit 8 oder 12 MHz läuft, das Timing wieder nicht passt. Bei 8 MHz rennt es doppelt so schnell. Da ist immer ein externer Timer besser.
    Multitasking-Betriebssysteme haben meist extra Systemaufrufe, da in der Zeit, die überbrückt werden soll, die Prozessorleistung auf die anderen Prozesse verteilt werden kann, genau so wie beim Warten auf eine Eingabe des Benutzers oder aif Rückmeldung irgendeiner Hardware.
    Concurrent CP/M hat z.B. das Kommando "P_DELAY", bei dem man die Anzahl "Ticks", die das System warten soll, angeben kann. Ist aber auch nicht ganz neutral, da die Ticks - laut Doku von DR - vom Netzteil kommt, sind also bei uns 50 Ticks pro Sekunde, in den USA dagegen 60.
    Aber dieser Aufruf führt dazu, dass der Scheduler das Programm solange stoppt, bis die Zeit abgelaufen ist.