Hi, Ansich sinds drei kleine Fragen die aber thematisch zusammenhängen. Ich mag nich rumspamen, daher stopf ich sie all4 in ein Post (hoffe das stört nicht). Ich schreibe über den UART Daten in den SRAM (ATmega8, also maximal 1Kb). Nach jedem neuen Byte erhöhe ich den Pointer um 1 (logisch, damit er nicht immer in die gleiche Zelle schreibt). Irgendwann ist der Pointer z.B. bei 681 (Byte). Soweit alles okay. Jetzt bekomme ich aber einen neuen Datensatz und muss von Byte 0 an schreiben. Hieraus ergibt sich die erste Frage: Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen? Der Pointer sollte dort denn auch bleiben, so das ich durch manuelles incrementieren weiterarbeiten kann. Das manuelle Z+ (oder Z-) frist eben emens viele Zyklen, wenn man bei 681 ist und zu 0 will. Frage zwei ergibt sich auch gleich daraus: kann ich auslesen, wo der Z-Pointer sich gerade befindet? Also z.b. den Positionswert von Z in r16 laden. Auch hier wieder das Problem, das ein manuelels Mitzählen unnötige Takte zieht. Für das Programm ist es sehr wichtig as es schnellst wie möglich ist, ich aber immer weiß wo sich der Pointer befindet (und weiß wieviele Byte im RAM stehen, weil ich den neuen Datensatz dann genau bis dahin lese udn alles weitere ignoriere) Frägelchen 3 ist eher eine Verständnissfrage: Wenn ich eienn Stack nutzen will, muss ich ihn ja Initalieieren. Ein Stack liegt im SRAM und wächst vom RAM-Ende zum RAM-Anfang. Wenn ich nun den RAM generell für Daten nutze (Z.b. für Messwerte) muss ich sicher aufpassen das ich immer unter dem gerade vom Stack belegten wert bleibe, weil der RAM meinen Stack überschreibt oder umgekehrt. Richtig? (Z.B. habe ich 50 Werte im Stack (mir verbleiben also 950 Byte RAM zur freien Nutzung. Würde ich nun 951 Byte ins RAM schreiben, hätte ich meinen letzten Wert im Stack (Wert 50) überschrieben. Stimmt meine Überlegung?) gespannt auf die Antworten Gruß, Uwe Wilke
Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen? z:=0; usw... B
Hallo, ich fange mal hinten an: ja, darauf musst Du selber aufpassen, sonst passiert genau das. Zum Z-Register: das sind ZH und ZL, also R30/R31, damit kannst Du logischerweise machen, was Du willst. clr ZL clr ZH ist eine mögliche Version, Z auf 0 zu bekommen. Wenn Z auf eine bestimmte Adresse setzen willst, dann mach es eben. ldi ZH,high($0150) ldi ZL,low($0150) lädt Z mit $0150 usw. usw. Gruß aus Berlin Michael
@Kai-uwe Wilke Ich nehme mal an du programmierst in Assembler. >Gibt es eine Möglichkeit direkt den Pointer (z.B. von Z) zu >Manipulieren, und mit ihm an eine beliebige Stelle im RAM zu springen? ldi zl,0xwhatever ldi zh,0xwhatever >Frage zwei ergibt sich auch gleich daraus: kann ich auslesen, wo der >Z-Pointer sich gerade befindet? Also z.b. den Positionswert von Z in r16 Z ist nur eine andere Bezeichung für r31/r30. Dementsprechend kann man alle Operationen damit ausführen (Load/Store/Compare/Whatever). >aufpassen das ich immer unter dem gerade vom Stack belegten wert bleibe, >weil der RAM meinen Stack überschreibt oder umgekehrt. Richtig? (Z.B. Ja. >habe ich 50 Werte im Stack (mir verbleiben also 950 Byte RAM zur freien >Nutzung. Würde ich nun 951 Byte ins RAM schreiben, hätte ich meinen >letzten Wert im Stack (Wert 50) überschrieben. Stimmt meine Überlegung?) Ja. MfG Falk
Danke für die Antworten, das brachte viel Licht ins Dunkel! :) Ja, ich schreibe direkt ist Assembler. Hmm, stimmt, X, Y und Z sind ja nicht anderes als Registerpaare. Das ich mit denen anstellen kann was ich will ist auch logisch. Ein Typischer Fall von: mal wieder den Wald vor Bäumen nicht gesehen. Logisch kann ich da Direkte Aderssangaben mit 0x$addr machen. Gibts die Möglichkeit das auch direkt in DEZIMAL anzugeben? Ich meine, klar kann ich Pro Register "0" bis "255" schreiben. Mich interessiert nun ob ich für den 16 Bit wert auch eine vergleichbare zahl (die praktischerweise auch gleich die Speicherzelle angibt) verwenden kann? Und zwar in einer Zeile (z.B. LDI ZL:ZH, "720") - in dem Fall 720 für Byt 720 im RAM. Klar könnt ich mir was basteln, was das tut. Würde aber wieder zusätzliche Rechenzeit verbrauchen. Notfalls reichst schon wenn ich die Adresse =x$addr in einer Zeile angeben könnt, insofern das geht. Wie schauts mit dem Stack aus, gibts dort eien art Zähler der mir sagt "zxy elemente auf dem Stack"?. Zu wissen wieviele Elemente auf dem Stack liegen (und wieviel weniger Bytes ich dementsprechen für den RAM habe) ist relevanter als zu wissen wieviel RAM ich belegt habe (und wieviel Stack mir bleibt) da halt der Stack das absolut wichtigere ist. Ich könnt nun einfachsagen "50 Stackplätze reservieren", aber ist mir etwas unsicher. Ein Angabe, wieviel gerade belegt sind (und womit ich den RAM-Platz dann dynamisch Einschränken kann) wäre vorteilhafter, denk ich. Grüß aus Berlin, Uwe
Normalerweise muss man Register einzeln laden. Mir wäre jedenfalls nichts bekannt, womit man 2 Register auf einmal mit einem Wert beschreiben kann. Mal von Multiplikation und so zeug abgesehen. Zum Stack: Du hast den Stackpointer den du auslesen kannst. Der richtige Ansatz wäre aber, nachzuzählen, wie groß der Stack maximal wird. Normalerweise brauchst du ihn doch nur für Interrupts. Der Speichert also 2 Byte (glaub ich). Dann wirst du noch eine gewisse Zahl an registern sichern. Ich bin bisher noch nie über 5 Byte Stackgröße gekommen, denn: Wenn ein Interrupt ausgelöst hat, sind die anderen blockiert. Außer natürlich wenn du da manuell rumpfuscht. Noch ne Wors-case-rechnung: Du sicherst im Interrupt ALLE Register, also 32 Byte. Dann kommst du auf 34 Byte Stack. Außer wenn du sonst noch Daten auf den Stack pushst. Und immer dran denken: Am Ende des Interrupts MUSS ein reti stehen. Sebastian
Hallo Sebastian: Naja es gibt ja (z.B.): adiw ZH:ZL, 1 vondaher ging ich einfach davon aus, dass sich das auf andere Sachen anwenden lässt . Interessanterweise motzt der Assembler bei "ldi ZH:HL, 100" nicht - morgen mal gucken was er in der Simulation damit tut. (werds dann sagen, was er macht) Mit dem Stack hast Du natürlich recht. Generell würd ich 50 reservieren (das ist mehr als viel). Aber es ist immer interessant zu wissen "was geht und was nicht", falls es mal relevant wird (z.b. bei dem ATtiny mit 64 Byte RAM). He, ja, RETI mit RET zu verwechseln hat lustige Folgen :) Gruß, Uwe Wilke
Die einfachste version sieht so aus: ldi ZL,LOW(zahl) ldi ZH,HIGH(zahl)
@Kai-uwe Wilke >Logisch kann ich da Direkte Aderssangaben mit 0x$addr machen. Gibts die >Möglichkeit das auch direkt in DEZIMAL anzugeben? Ich meine, klar kann Denk dran, mit absoluten Speicheradressen sollte man möglichst wenig hantieren, das geht schief wenn man mal was ändert (Variablen im RAM). Nimm lieber die professionelle Lösung mit Labels. Den Rest macht der Assembler. Ist auch wesentlich intutiver lesbar. .dseg .org 0x60 my_buffer: .db 500 .cseg ldi zl,low(my_buffer) ldi zh,high(my_buffer) >könnt ich mir was basteln, was das tut. Würde aber wieder zusätzliche >Rechenzeit verbrauchen. Notfalls reichst schon wenn ich die Adresse Auf einer 8 Bit CPU kannst du nur 8 Bit Werte dirket beschreiben. Aber zwei LDIs tun niemandem weh. >Wie schauts mit dem Stack aus, gibts dort eien art Zähler der mir sagt >"zxy elemente auf dem Stack"?. Zu wissen wieviele Elemente auf dem Stack Der Stack selber! Einfach die Differenz bilden aus Stack_am_anfang-stack_aktuell MfG Falk
@Hannes Lux >my_buffer: .byte 500 >könnte bei AVR-Studio wirksamer sein... Kleiner Aufmerksamkeitstest ;-) MfG Falk
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.