Forum: Mikrocontroller und Digitale Elektronik Programmteil in assembler nicht verständlich


von Dirk S. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo alle zusammen,

und zwar wollte ich auch einmal anfangen einen ATMega 8 zu 
programmieren. (in Assembler)

Mein Projekt: Thermometeranzeige für meine Ätzanlage

Da ich aber noch keine Ahnung habe, habe ich mir erst einmal ein 
ähnliches Programm gesucht und das analysiert.
Ich hab ein paar Fragen zu diesem Programm „Mehrere 7-Segment Anzeigen 
gleichzeitig (Multiplexing)“ (siehe Anhang).

Das hier kann ich nicht nachvollziehen:

out_number:
           push    temp
           push    temp1

           ldi     temp2, -1              ; Die Tausenderstelle 
bestimmen
_out_tausend:
           inc     temp2
           subi    temp, low(1000)        ; -1000
           sbci    temp1, high(1000)
           brcc    _out_tausend

           ldi     ZL, low(2*Codes)       ; fuer diese Ziffer das 
Codemuster fuer
           ldi     ZH, high(2*Codes)      ; die Anzeige in der 
Codetabelle nachschlagen
           add     ZL, temp2

           lpm
           sts     Segment3, r0           ; und dieses Muster im SRAM 
ablegen
                                              ; die OvI Routine sorgt 
dann duer die Anzeige
           ldi     temp2, 10


Was ist hier mit der 1000 gemeint ?  Ich hab das mal durchs AVR Studio 
laufen lassen und er schreibt in das Register temp nur „19“ , in das 
Register temp1 „ FC “ .  Bei dem Teil mit der 1000 verstehe ich 
irgendwie nur Bahnhof.


Als Kommentar steht „; -1000“, obwohl in den Klammern nur 1000 steht. 
Ist das so eine Festlegung, dass man + und - vertauschen muss?



Woran kann es liegen, dass er den Befehl „call“ im AVR Studio als Fehler 
deklariert? Ich habe diesen durch den Befehl rjmp ersetzt.

Könntet ihr mir vielleicht einmal die Berechnung erklären ? Da steig ich 
nicht hinter.

Danke und Gruß von Dirk

von ichich (Gast)


Lesenswert?

Der ATmega8 hat keinen CALL Befehl.
Der heißt hier -> RCALL.

von Johannes M. (johnny-m)


Lesenswert?

> Der ATmega8 hat keinen CALL Befehl.
> Der heißt hier -> RCALL.
Und v.a. gehört zu einem "(r)call" IMMER ein "ret"! Wenn Du nur den 
call durch rjmp ersetzt, das ret am Ende (von dessen Existenz ich jetzt 
mal ausgehe) aber stehen lässt, gibt es vermutlich irgendwann einen 
Stack-Underflow.

call und jmp ohne "r" gibts nur bei AVRs mit mehr als 8 KiB Flash.

Wo die 1000 jetzt konkret herkommen, kann ich in Unkenntnis des 
Projektes nicht ersehen, aber an der Stelle oben wird einfach der Wert 
1000 von einem anderen Wert abgezogen (was ja auch im Kommentar 
zumindest angedeutet ist). Da "1000" aber nicht in ein 8-Bit-Register 
passt, muss die Subtraktion in zwei Operationen durchgeführt werden, 
nämlich nach Low- und High-Byte getrennt.

> Als Kommentar steht „; -1000“, obwohl in den Klammern nur 1000 steht.
> Ist das so eine Festlegung, dass man + und - vertauschen muss?
Nö. Da steht eben, dass "Ausgangswert - 1000" gerechnet wird. Schau Dir 
im Instruction Set Manual mal an, was die Befehle subi und sbci machen 
(Kleiner Tipp: Sie subtrahieren etwas...).

Übrigens: Wenn Du mit AVRStudio arbeitest, dann nutze einfach die Hilfe. 
Da steht alles drin, was man wissen muss. Wenn Du den Cursor auf einen 
Assembler-Befehl setzt und F1 drückst, kommt sofort die Beschreibung des 
Befehls. Da solltest Du generell ansetzen.

Und noch was:
Programmcode wird NIEMALS als Word-Dokument angehängt! Entweder als 
.asm-Datei oder einfach als .txt.

von Peter D. (peda)


Lesenswert?

ichich wrote:
> Der ATmega8 hat keinen CALL Befehl.

Nicht mehr.

Die ersten Mega8 hatten einen CALL Befehl.

Aber irgendwann wurde er aus dem Datenblatt entfernt und noch etwas 
später wurde er im Assembler als ungültig erklärt.

Wenn man ihn benutzt, wird er korrekt ausgeführt.


Peter

von Dieter W. (dds5)


Lesenswert?

>  Bei dem Teil mit der 1000 verstehe ich irgendwie nur Bahnhof.

Da wird von dem vorher mit 2x push gesicherten 16Bit Wert in temp/temp1 
so oft 1000 abgezogen bis er negativ wird.
Als Ergebnis steht dann in temp2, wie oft das Abziehen ging und damit 
hast du den Wert der auf der Tausender Stelle angezeigt werden muss.

von Hannes L. (hannes)


Lesenswert?

Tja, wo kommen nun die 1000 her...

Das Programm soll eine mehrstellige Zahl, die in zwei Registern 
gespeichert ist, in mehrere Ziffern zerlegen. Dazu wird solange der Wert 
der Dezimalstelle (1000 bei der Tausenderstelle, 100 bei der 
Hunderterstelle) subtrahiert (und dabei der Ziffernwert der Stelle 
addiert), wie das Ergebnis nicht unter 0 kommt. Das entspricht etwa 
einer Division durch 1000 (oder 100). Ein optimiertes Beispiel findest 
Du im AVR-Tutorial im Kapitel LCD.

...

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
Noch kein Account? Hier anmelden.