Forum: Mikrocontroller und Digitale Elektronik 16 Bit RAM-Zugriff beim AVR Assembler


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Holler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,
alle Jubeljahre beschäftige ich mich mit Mini-Controller-Projekten, so 
dass ich nicht wirklich tief in der Materie stecke.

Momentan habe ich einen kleinen Temperatur- und Spannungswächter auf dem 
Tisch, soll mit einem ATTiny45 realisiert werden (habe ich gerade in der 
Bastelkiste, ist schon überdimmensioniert).

Zum Punkt: ich möchte 16 Bit Messwerte im RAM mit 16 Bit Konstanten 
vergleichen. Dabei fällt auf, dass der Zugriff mit low / high(Name) bei 
den Konstanten funktioniert, aber bei Variablen im RAM Müll liefert.
Beispiel:

;Konstante
.equ    NTCblau     = 0x0123  ; kalt, <60 Grad

;Variable im RAM
.DSEG                           ; Umschalten auf das SRAM Datensegment
NTCMittel:    .BYTE  2
;...
; Das funktioniert
ldi  r22, low (NTCblau)
ldi  r23, high(NTCblau)

;Das liefert Müll
lds  r22, low (NTCMittel)
lds  r23, high(NTCMittel)

;Der Workaround
lds  r22, NTCMittel
lds  r23, NTCMittel+1

Kann man das low/high Konstrukt nicht für RAM-Zugriff nutzen?
Warum meckert dann der Assembler nicht?

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Hast du denn überhaupt erst was an die Stelle im RAM geschrieben?! 
Einfach nur etwas Laden liefert irgendwelche zufälligen Werte, die beim 
Reset da drin stehen.

von Axel S. (a-za-z0-9)


Bewertung
0 lesenswert
nicht lesenswert
Holler schrieb:
> Kann man das low/high Konstrukt nicht für RAM-Zugriff nutzen?

Nein. Es ergibt an dieser Stelle auch überhaupt keinen Sinn. NTCblau ist 
eine Konstante, die kann der Assembler zur Übersetzungszeit in low- und 
high-Teil zerlegen. NTCMittel hingegen ist eine Adresse. Eine 16-Bit 
Variable belegt im Speicher aber zwei aufeinanderfolgende 
Speicherplätze. Vulgo: die Startadresse und Startadresse+1

> Warum meckert dann der Assembler nicht?

Weil es syntaktisch korrekt ist.

Wenn du mit derartigen Trivialitäten wie dem Zugriff auf Variablen mit 
mehr als einem Byte überfordert bist, dann verwende nicht Assembler, 
sondern eine Hochsprache. Z.B. C. Oder meinetwegen auch BASIC (BASCOM) 
oder LunaAVR. Die verbergen diese Details vor dem Anwender.

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Äh, moment, falsch gelesen.

Holler schrieb:
> ;Das liefert Müll
> lds  r22, low (NTCMittel)
> lds  r23, high(NTCMittel)
Das kann nicht funktionieren... Das lädt r22 von der Adresse 
low(NTCMittel) - also einer völlig anderen als gewünscht, und r23 von 
high(NTCMittel), also von einer noch ganz anderen Adresse.

Holler schrieb:
> lds  r22, NTCMittel
> lds  r23, NTCMittel+1
Das ist richtig - r22 kommt von der Adresse NTCMittel, und r23 von der 
nächsten.

von Sascha W. (sascha-w)


Bewertung
0 lesenswert
nicht lesenswert
Holler schrieb:
> Hallo zusammen,
> alle Jubeljahre beschäftige ich mich mit Mini-Controller-Projekten, so
> dass ich nicht wirklich tief in der Materie stecke.
>
> Momentan habe ich einen kleinen Temperatur- und Spannungswächter auf dem
> Tisch, soll mit einem ATTiny45 realisiert werden (habe ich gerade in der
> Bastelkiste, ist schon überdimmensioniert).
>
> Zum Punkt: ich möchte 16 Bit Messwerte im RAM mit 16 Bit Konstanten
> vergleichen. Dabei fällt auf, dass der Zugriff mit low / high(Name) bei
> den Konstanten funktioniert, aber bei Variablen im RAM Müll liefert.
> Beispiel:
>
> ;Konstante
> .equ    NTCblau     = 0x0123  ; kalt, <60 Grad
>
> ;Variable im RAM
> .DSEG                           ; Umschalten auf das SRAM Datensegment
> NTCMittel:    .BYTE  2
> ;...
> ; Das funktioniert
> ldi  r22, low (NTCblau)
> ldi  r23, high(NTCblau)
>
> ;Das liefert Müll
> lds  r22, low (NTCMittel)
> lds  r23, high(NTCMittel)
>
> ;Der Workaround
> lds  r22, NTCMittel
> lds  r23, NTCMittel+1
>
> Kann man das low/high Konstrukt nicht für RAM-Zugriff nutzen?
Nein,
lds erwartet eine 16Bit-Speicheradresse des SRAM,
Low liefert dir die unteren 8-Bit der Adresse, High die oberen 8-Bit
1
lds r22,NTCMittel
2
lds r23,NTCMittel+1
ist die richtige Wahl

ich habe mir da entsprechende Makros angelegt
1
.macro ldsw
2
lds @0H,@1
3
lds @0L,@1+1
4
.endmacro
5
6
im Code:
7
lsw X,NTCMittel

Ob du im Ram erst das H und dann das L Byte oder umgekehrt speicherst 
bleibt dir überlassen.

Sascha

von Fred (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ich würde NTCMittel ja mal als .Word Variable definieren, dann klappts 
vielleich auch mit dem Low/High Zugriff...

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Fred schrieb:
> Ich würde NTCMittel ja mal als .Word Variable definieren, dann klappts
> vielleich auch mit dem Low/High Zugriff...

Völlig egal, Assembler ist nicht typisiert... Für manche Leute der 
Hauptgrund, das zu verwenden!

von Holler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Danke für die superschnellen Antworten!

@Dr. Sommer (Gast): ja da stand etwas sinnvolles im RAM. Der Zugriff 
über das low/high Kontrukt lieferte aber weder den Inhalt noch die 
Adresse sondern irgendwas beliebiges.

@Axel Schwenke: Überfordert fühle ich mich nicht, Assembler ist schon 
das einfachst mögliche Werkzeug. Habe die Lösung ja schon in meinem 
Eingangspost skizziert. Dachte halt, dass der Assembler das selbst 
auflösen kann wenn er schon nicht meckert. Das Kontextwissen hat er ja.
Man könnte sich den Maschinencode ansehen was der Assembler daraus 
macht.

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Holler schrieb:
> Dachte halt, dass der Assembler das selbst
> auflösen kann wenn er schon nicht meckert. Das Kontextwissen hat er ja.

Naja, was genau soll der Assembler da sehen? Er sieht zwei völlig 
unterschiedliche Adressen, aber das kann ja Absicht sein. Woher soll er 
wissen dass du die Adressen falsch berechnest, und dass r22 und r23 
zusammen gehören?

Disassemblierten Code anschauen kann helfen...

von Holler (Gast)


Bewertung
0 lesenswert
nicht lesenswert
War viel zu langsam mit meiner Antwort: vielen Dank für die Posts, habe 
verstanden was das low/high Konstrukt bewirkt.

von Fred (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Disassemblierten Code anschauen kann helfen...

Was soll der Quatsch? Das Assemblat hast Du vor Dir- da gibts nix zu 
"Disassemblieren"...

von Dr. Sommer (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Fred schrieb:
> Was soll der Quatsch? Das Assemblat hast Du vor Dir- da gibts nix zu
> "Disassemblieren"...
Doch, in der Disassembly sieht man die vom Assembler/Linker berechneten 
Adressen in "Reinform". Da würde man erkennen, dass das genutzte 
low()/high() -Konstrukt nicht das beabsichtigte produziert.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
low und high sind im Prinzip nur Macros. Sie machen folgendes:
1
#define low(x) (x & 0xFF)
2
#define high(x) low(x >> 8)

Damit ist auch klar, warum sie nicht im RAM verwendbar sind.

von Fred (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Dr. Sommer schrieb:
> Fred schrieb:
> Was soll der Quatsch? Das Assemblat hast Du vor Dir- da gibts nix zu
> "Disassemblieren"...
>
> Doch, in der Disassembly sieht man die vom Assembler/Linker berechneten
> Adressen in "Reinform". Da würde man erkennen, dass das genutzte
> low()/high() -Konstrukt nicht das beabsichtigte produziert.

Ok, da hast Du Recht.
Wenn die Variable z.B. auf 400/401H steht würde via lds zum einen (low) 
der Inhalt von 00H, zum anderen (high) von 04H gelesen. Was sich auf 
diesen Adressen lesbar befindet steht noch einmal auf einem anderen 
Blatt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.