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?
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.
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.
Ä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.
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
Ich würde NTCMittel ja mal als .Word Variable definieren, dann klappts vielleich auch mit dem Low/High Zugriff...
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!
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.
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...
War viel zu langsam mit meiner Antwort: vielen Dank für die Posts, habe verstanden was das low/high Konstrukt bewirkt.
Dr. Sommer schrieb: > Disassemblierten Code anschauen kann helfen... Was soll der Quatsch? Das Assemblat hast Du vor Dir- da gibts nix zu "Disassemblieren"...
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.
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.
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.
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.