Sprünge - ohne Bedingung = unbedingte Sprünge ("Programmieren" lernen)

  • Sprünge in Programmen düften von BASIC etc. hinlänglich bekannt sein.


    Sie bedeuten, daß man zunächst an einer Stelle im Programm was macht, dann den Sprungbefehl ausführt und an dessen Ziel direkt mit dem Programmablauf fortfährt.


    Es gibt sie natürlich auch auf Maschinenebene. Dort wechselt man damit einfach von einer Adresse auf eine andere.


    Der unbedingte Sprung bedeutet dabei einfach, daß es völlig egal ist, was sonst im Rechenwerk passiert, der Sprung wird AUF JEDEN FALL, also UNBEDINGT, d.h. OHNE BEDINGUNG, ausgeführt.


    Das Gegenteil sind bedingte Sprünge, die die Adresse nur wechseln, wenn eine bestimmte Voraussetzung erfüllt ist. (Zum Beispiel, wenn ein Überlauf aufgetreten ist.)

  • =6502=


    Es gibt hier nur einen Sprung, der völlig freies Springen im Adressbereich ermöglicht.

    Das ist der Befehl

    JMP - Jump


    Dafür wird nur noch die Adresse benötigt, an die gesprungen wird, also z.B. JMP $5500


    Es wird jetzt auch das Rätsel der ersten Zahl in der Statusleiste gelöst. Dort wird nämlich einfach die momentan aktuelle Adresse angezeigt, an der der Prozessor gerade nach seinem nächsten Befehl suchen würde (wenn nicht gerade eine Unterbrechung passiert wäre und der Status angezeigt würde).


    Diesmal ganz kurz und einfach


    Das Programm


    .5000 JMP $5500

    .5003 BRK


    und


    .5500 BRK



    mit G5000


    springt also der Befehl JMP an die Zieladresse $5500


    Der erste Wert in der Statuszeile zeigt dementsprechend vor Programmbeginn auf einen Standardwert nach Reset, danach aber auf die Adresse $5502 und somit ins richtige Zielgebiet.


    Interessant wird es, wenn man einen Rücksprung einfügt, mit


    .5500 JMP $5000


    Man solle sich bitte vorher überlegen, was dabei passiert !


    Starten ist wahlweise mit G 5000 oder G 5500 möglich.

  • Vielen Dank für die Arbeit die du dir da machst !! Falls es erlaubt ist, eine kleine Ergänzung. Das hier ist ein Maschinensprachemonitor, der assemblieren und disassemblieren kann. Er hat Zeilennummer, wie man es vom Commodore Basic kennt. Aber zB der Turboassembler hat keine Zeilennummern. Wenn man ein Unterprogramm schreibt, muss dieses mit einem Label versehen sein. Also einem Namen mit einem Doppelpunkt, mit JMP kann man dann zu diesem Label mit JMP NAMEDESLABELS springen.


    JMP kann man also mit dem GOTO Befehl aus Basic vergleichen.


    Für mich wäre interessant zu wissen, wie man nur unter einer bestimmten Bedingung einen JMP ausführen kann. Quasi wie IF x=1 then goto 10..



    Gruss Jan

    Es gibt 10 Arten von Menschen. Die einen verstehen das Binärsystem, die anderen nicht.

  • Ja sorry. Natürlich sind es Speicheradressen, du hast Recht, aber man kann sich daran orientieren wie bei den Zeilennummern im Basic. Ich denke auch nicht, in den Maschinensprachemonitoren sind normalerweise recht gewöhnliche Assembler..

    Es gibt 10 Arten von Menschen. Die einen verstehen das Binärsystem, die anderen nicht.

  • Also, ich habe mir das ja so vorgestellt, daß jeder (!) der mag ein solches Thema anfangen kann. Es in den INndex schreibt und dann in einem neuen Thread mit dem Namen aus dem Index was dazu.

    Dabei sollen die Index Themen bzw. die dazugehörigen Thread Themen so allgemein gehalten werden, daß man sie für mehrere Architekturen quasi als Lehrbuch lesen kann. Dazu kommen dann noch entsprechende Beispiele für bestimmte Geräte - wenn als jemand z.B. eine allgemeine Registerbeschreibung für Z80 machen will, dann sollte der evtl. unter das schon vorhandene Kapitel Register, aber eben mit dem Vorsatz =Z80=, insebsondere, wenn da Z80 Sourcecode drin auftaucht. Handelt es sich dagegen um allgemeine Info zum Thema Register, dann gehört das natürlich auch dorthin, aber eben ohne die Einschränkung auf Z80.



    Die Antwort auf die Frage würde also am ehesten in ein Kapitel "Bedingte Sprünge" passen, das gibts aber eben noch nicht. Daher mal kurz eine Variante dazu


    LDA $wert

    CMP #$ 01

    BNE $(label weiter im Programm)

    JMP nach-adresse-10 ----------------------------------->>

    label weiter im Programm


    Im Akku wird der Wert von x geladen, dann wird x mir dem fixen Wert #$01 verglichen, wenn das so wäre würde das Zero Flag gesetzt - darauf wird nun mit BNE getestet, wenn der Vergleich ungleich war (NE = not equal) wird die JMP Anweisung übersprungen und direkt dahinter weitergemacht - waren x und Vergleichswert (#$01) dagegen gleich, macht BNE quasi nichts, dafür aber wird JMP erreicht und das springt dann in die Zeile wo GOTO 10 weiterginge

    (PS: Das ist relativ unelegant, aber es macht genau das, was Dein IF machen würde)

  • Einige Prozessoren (z.B. Z80, 80x86) können auch relative Sprünge durchführen.

    Hierbei wird keine absolte Adresse als Ziel angegeben, sondern der Offset vom aktuellen Programmcounter zur gewünschten Zieladresse.

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

  • =Z80=


    Beim Z80 heisst der Befehl Jump Relative, mnemonic JR

    Der Offset ist 8bit breit und entspricht somit -126 bis +129 Bytes.


    Code
    1. L1: jr -2 ; Endlosschleife


    Wer jetzt aufgepasst hat, fragt (zu recht)warum 8 bit und -126 bis +129 bzw -2 bei der Endlosschleife.


    Der Offset wird auf die Adresse nach dem JR Befehl berechnet.

    Das ist auch beim 8086 so und hat mit dem CPU-internen Ablauf zu tun.

    Nachdem der Befehl gelesen und dekodiert ist, steht der PC (Programmcounter) schon auf dm nächsten Befehl und danach wird erst der Offset auf den PC addiert.


    Nachtrag:

    Der 8080 / 8085 kennt den Befehl nicht!

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)

    Einmal editiert, zuletzt von funkenzupfer ()

  • Und wer sich jetzt fragt: "Was soll der Quatsch" hat heute völlig Recht. Denn es ging bei den relativen Sprüngen tatsächlich nur darum, ein Byte des kostbaren Speicherplatzes zu sparen - sonst nichts. Ansonsten macht ein relativer Sprung nichts anderes als ein absoluter Sprung mit einer 16 Bit Adresse, die den Zugriff auf den gesamten Speicher ermöglicht (bei einem typischen 8-Bitter).


    Im Übrigen hat man bei der Verwendung von Assembler - wie oben schon gesagt - nicht mit Adressen, sondern mit Labels oder Sprungmarken gearbeitet. Das war gerade bei relativen Sprüngen deutlich bequemer, weil man sich die Rechnerei sparte.


    Allerdings gibt es auch ein Einsatzgebiet, wo relative Sprünge einen Riesenvorteil bieten: verschiebbarer Code. Wenn wir ein Stück Code an eine andere Speicherstelle schieben (z.B. vom ROM ins RAM), stimmen die absoluten Adressen innerhalb des Codestücks nicht mehr und müssen alle angepasst werden. Relative Sprünge bleiben dagegen korrekt.


    Das ist aber schon hohe Kunst der Assemblerprogrammierung 8-)

  • Im Übrigen hat man bei der Verwendung von Assembler - wie oben schon gesagt - nicht mit Adressen, sondern mit Labels oder Sprungmarken gearbeitet.

    Aber nicht immer kann man einen Assembler einsetzen.

    Manchmal gibt es gar keinen und dann muss man das ganze von Hand kodieren.


    Ich hatte das handkodieren auf der CC17 in Berlin einigen Leuten gezeigt und erklärt. Das Stauen war beeindruckend.

    ;------------------------------------
    ;----- ENABLE NMI INTERRUPTS
    (aus: IBM BIOS Source Listing)