Hallo Leute, ich arbeite mich zur Zeit auf einem ATMEGA32 in Assembler ein (bin also Anfänger). Bei einem kleinen Progrämmchen habe ich nun ein Problem festgestellt. Die Fehlerursache habe ich ansich erkannt, weiß aber nicht wie ich es besser machen kann. Daher meine Frage an euch, ob Ihr mir weiterhelfen könnt. Folgende Situation, ich versuche eine Uhr mittels Assembler zu programmieren. Vorhandene Beispielcodes in der Codesammlung habe ich angeschaut, dass eigentliche Problem konnte ich damit aber nicht lösen. Wie lasse ich das Programm bedingt in ein Unterprogramm springen, also wie löst man sowas in Assembler? Zur Erläuterung was ich im Hinterkopf habe, ein kurzes Beispiel in C (ich weiß, dass dies 1:1 in Assembler nicht möglich ist, es dient also nur der Erläuterung was ich erreichen möchte): //var=Laufvariable, wird "irgendwo" hochgezählt if (var==x) // var identisch mit x? { unterprogramm(); } Ich habe nun folgendes geschrieben (Auszug aus meinem Programm): loop: cpi sekunde,60 //compare register & Konstante breq min //verzweige zu "min" wenn z flag gesetzt rjmp loop min: ldi sekunde, 0 inc minute ret (Hinweis: am Programmanfang habe ich ".def sekunde = R19" & ".def minute = R20" stehen , sind also beides register wie es sein sollte) Mit meinem JTAG Debugger habe ich gemerkt, dass bei "breq min" der PC anscheinend nicht auf dem Stack gesichert wird (Adresse verkleinert sich nicht...), beim anschliessenden ret springt er dann wohl ins nirwana, JTAG ICE warnt dabei vor invalid value (0x7FFFFFFF) und mein Programm fängt ganz von vorne an. Offensichtlich ist breq (wohl auch brne etc.) nicht dafür geeignet, weil der PC nicht gesichert wird, richtig? Einen Rücksprung aus einer Interruptroutine habe ich probiert, weiß also wie es aussehen müsste (was Stack und PC angeht). Wie muss ich es stattdessen lösen? Für ein kurzes, kommentiertes Beispiel wäre ich dankbar. Danke und Gruß Armin
breq macht einen relativen Sprung. Das hat nix mit ret zu tun. Unterprogrammaufrufe gehen mit call bzw. rcall. Schau Dir den Befehlssatz mal genauer an. Du müsstest, wenn Du mit der obigen Bedingung springen willst, was in der Art cpi sekunde, 60 brne weiter call min weiter: ;weiter im Programm min: ldi sekunde, 0 inc minute ret Dann springt das Programm bei ret wieder zurück (also nach "weiter")
"call" dürfte dich interessieren. Es dürfte dann auf ein Konstukt hinauslaufen, dass die beiden Variablen vergleicht und bei "negativem" Ergebnis die folgende Anweisung überspringt. In diesem Fall wäre die Anweisung dann das "call". Pseudocode: (ich kann Asm lesen, aber nicht schreiben...) anfang: . . . compare X,Y skip if equal call ungleich allgemeines Weitermachen . . . jmp anfang ungleich: . . . ret
...Oder mit der Schleife von oben: loop: cpi sekunde, 60 brne loop call min min: ldi sekunde, 0 inc minute ret
danke, besonders @johnny m., habe deinen ersten Tip verwendet, da ja hier noch ein Unterprogramm Stunde, u.a. kommen wird. Hat auf Anhieb funktioniert und habs auch verstanden...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.