Assembler - AVR Frage

Gast #444631
Lesenswert?
• ▲
▼
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
Gast #444640
Lesenswert?
• ▲
▼
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")
Gast #444641
Lesenswert?
• ▲
▼
"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

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.