hat jemand ne Ahnung wie man den Programm Counter auslesen kann. Im Elektor Buch "AVR-Mikrocontroller-Praxis" von den Volpe's steht auf Seite 12 im Kapitel 2.2 AVR-Architektur das sich dieser im I/O - Adreßbereich befinden soll. Habe alle Datenblätter der Basic Line durchforstet kann aber nirgendwo finden, wie man den PC (Programm Counter) auslesen kann.
Wieso willst du den auslesen? Das Programm weiss doch, wo es gerade ist ;-)
I/O Adressbereich ist der Adressbereich, wo man die Ports und die Special-Function Register findet. Sollte kein Problem sein. Ansonsten per Call die Adresse auf den Stack schreiben und vom Stack zurücklesen. Aber wie oben bereits beschrieben: Der PC hat den Wert der Adresse, an der sich das Programm gerade befindet...
Kann schon sinnvoll sein, z.B. wenn man positionsunabhängigen Code braucht, ohne aber jetzt noch eine Relozierungsfunktion schreiben zu wollen, der z.B. auch Daten enthält und man keinen relativen Lesebefehl hat. Ok, etwas viele wenn's, vielleicht doch nicht so sinnvoll, aber am C64 habe ich das auch schonmal für dynamisches Linken in Assembler verwendet :-)
Also hier:
formatting link
kann man ein RCALL finden, sodaß es dann die Kombination
rcall label label: pop
das gewünschte Ergebnis im Rd-Register liefern sollte. Der Assembler kümmert sich dann darum, daß die Anweisung "rcall label" in irgendwas wie "rcall 1" oder "rcall 3" oder so umgesetzt wird.
--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Das ist die Basis für viele schöne Dinge, die weit über jedes simple C++ vtable hinausgehen und bei späteren Softwareentwicklern, die das dann warten müssen, für Freude sorgt :-)
--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Oh Graus, selbstmodifizierender Code! Sowas macht man sauber über indirekte Adressierung mit der Zeropage :-) (die üblichen Bereiche von $FB bis $FE, wenn der Kernel noch was machen soll)
Ich sehe aber nicht, was dein Code sonst mit relativer Adressierung und dynamischen Linking zu tun hat, also zur Laufzeit z.B. ein Scrolltext-Modul von der Floppy reinladen, danach ein Sound-Modul, initialisieren, starten, wieder entladen, neue Module reinladen usw., also was man bei größeren Demos alles so gebraucht hat.
--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
ich überprüfe Zahlenwerte von 1 bis 3. Und falls ein anderer Wert vorliegt habe ich irgendwo ein Programmfehler gemacht und möchte deshalb wissen wo dieser ungefähr ist.
Nö. Das wäre ja langsamer :) Außerdem ist die Zeropage sowieso *immer* schon voll. Und "4 Bytes Zeropage gescrubt" ist ein häßlicher Seiteneffekt. Ein richtiger H4> Ich sehe aber nicht, was dein Code sonst mit relativer Adressierung und
Es adressiert die Daten relativ. Egal, wohin der obige Code assembliert wird, er läuft immer. Und wenn die Entwicklungsumgebung einen Linker hat, dann wird das 'loop' Symbol erst beim Linken festgelegt.
Es ist kein position independent code, falls du das meintest. Der müßte dann tatsächlich zur Laufzeit den PC auslesen und die beiden INCs fixieren. Ich wüßte bloß nicht, warum man das machen sollte. Dynamische Libs ergeben weder auf dem C64 noch auf dem AVR einen Sinn.
Wir haben es hier mit einer Harvard-Architektur zu tuen. Da würde positionsunabhängiger oder relozierbarer Code allenfalls für einen Bootloader eine Rolle spielen, der variable Module von einem Host nachlädt.
Der braucht aber sowieso eben diesen Host als Gegenstück. Wenn also überhaupt irgendwas, würde der das sinnvollerweise erledigen. Und er bräuchte dazu natürlich nicht den PC auslesen, sondern den Code einfach nur ab übermittelter Basisadresse kompilieren.
Aber viel Sinn würde die Sache eh' nicht machen, weil der Flash bei intensivem Modulgetausche eh' nach relativ kurzer Zeit hinüber wäre.
ich überprüfe Zahlenwerte von 1 bis 3. Und falls ein anderer Wert vorliegt habe ich irgendwo ein Programmfehler gemacht und möchte deshalb wissen wo dieser ungefähr ist, da ich an mehreren Stellen im Programm solche Überprüfungen vornehme.
Bei Motorolas MC68HC11 gibt es einen Illegal Opcode Interrupt und den benutzte ich damals um auf einem LCD die Adresse auszugeben wo dieser auftrat. So etwas möchte mit den AVR auch machen.
Ich glaube mit dem "rcall" (relativ) leg ich mich evtl. selber rein.
.... breq drei ;Verzweige bei Übereinstummung... rcall error ;...ansonsten Fehler im Programm. error: pop temph ;High-Byte... pop templ ;...und Low-Byte der Programmadresse vom... ;..Stack holen. rcall Lcd_out ;Programmadresse auf dem LCD ausgeben. ende: rjmp ende ;Endlosschleife
und dann fällt mir ein - alles irgendwie Mist. Wie wird die Rücksprungadresse auf dem Stack gelegt ? Erst Low-Byte dann High-Byte ? Der Stack arbeitet auf jedenfall nach dem LIFO Prinzip. Last In -> First Out. Falls ich im Simulator alles richtig verstanden habe, stimmt das Programm zufälligerweise so weit.
Man kann sich auch ein kreatives GOTO basteln indem man erst per PUSH sich einen Programmzaehler auf den Stack schreibt und dann RTS aufruft. Das freut den, der diesen Code mal warten muss spaeter ungemein.
Naja, so unüblich ist das nicht. Zumindest jeder, der mal präemptives Multitasking bzw federgewichtige Threads selbst implementiert hat, hat sowas schonmal gesehen.
Viele Grüße, Johannes
--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
Für sowas hilft nur RTFM :-) Ich finde das aber generell nicht besonders sinnvoll. Wieso nicht einfach eine feste Nummer laden und die dann ausgeben? So musst du ja das Listing-File des Assemblers erst laden, dann dort nachschauen, was an der Adresse steht und danach ggf. wieder im Sourcecode dieselbe Stelle suchen, wenn du was ändern willst. Bei genügend Speicher, besseren Macrofähigkeiten und Textdisplay oder seriellem Port, könnte man bestimmt auch sowas programmieren:
assert(Rd=3, "Rd ungleich 3 bei Stelle Foobar")
--
Frank Buss, fb@frank-buss.de
http://www.frank-buss.de, http://www.it4-systems.de
Ist mir trotzdem noch nicht ganz klar, wie das funktionieren soll, und wie du die Fehlerposition bestimmen willst.
Denkbar wäre, dass im Fehlerfall ein INT ausgelöst wird. In der INT-Routine könnte man dann mit Pop die Rücksprungadresse auslesen. Wenn man die dann wieder zurückpusht, dann kann das Programm sogar direkt weiterlaufen.
Beispiel für AVR Assembler kann ich leider nicht liefern, weil ich den nur in GCC programmiere
Als Alternative kann man an den betreffenden Stellen auch einfach eine entsprechende Fehlernummer ausgeben.
So einen Interrupt koennen AVRs nicht erzeugen. Laut Atmel:
formatting link
werden Illegal Opcodes einfach als NOP ausgefuehrt.
Um die Integritaet des Flash zu pruefen (AVR kann wegen Harvard Architektur keine Befehle aus dem RAM ausfuehren) kannst du eine Checksumme mit hinein brennen und den AVR die neu berechnen und vergleichen lassen.
Der 2313 hat halt kein CALL (absolut) weil die relative Adressierung sein komplettes Flash abdecken kann. Die Adresse auf dem Stack waere in beiden Faellen die des naechsten Befehls.
Ich wuerde sagen ja. Die ausgelesene Adresse ist die von "pop temph", alse dem Label "error".
Frank meint eine Loesung in der Art:
---------------------------------------------------------------------- .... breq drei ;Verzweige bei Übereinstummung... E1: ldi temph, 'E' ;Fehlermeldung laden ldi templ, '1' rcall Lcd_out ;Fehlermeldung auf dem LCD ausgeben. rjmp ende ;Endlosschleife
---------------------------------------------------------------------- Das Display zeigt an "E1" und man kann einfach nach der Stelle im Source suchen.
breq drei ;Verzweige bei Übereinstummung... E1: ldi temph, hi8(E1) ;lade Adresse von E1 nach temp ldi templ, lo8(E1) rcall Lcd_out ;Fehlermeldung auf dem LCD ausgeben. rjmp ende ;Endlosschleife
Zumindest einige AVRs können sowas ähnliches. Die, denen Atmel die BREAK-Instruktion spendiert hat. Man braucht allerdings natürlich einen entsprechenden Debugger, um sie nutzen zu können.
Das wäre sie auch im Falle eines absoluten CALLs. Ich sehe da kein Problem.
ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here.
All logos and trade names are the property of their respective owners.