Hallo Leute
ich habe mich vor kurzem angefagen mit Assembler zu beschäftigen. Ich
wollte einen PIC16F628 programmieren. Habe ein Projekt von Microchip
downgeloadet und versuche nachzuvollziehen was und wie die dort
programmiert haben und bin gleich auf was gestoßen. Finde leider nichts
aussagekräftiges was diese Zeilen zu bedeuten haben:
STARTUP CODE
INTVCT CODE
MAIN_SETUP CODE
EE_DATA CODE 0x2100
Zwischen den Zeilen ist Quelltext, den ich einigermaßen verstehe.
Meine Vermutung ist, dass z.B. STARTUP CODE anstelle von org 0 steht
und INTVCT CODE anstelle von org 4 den rest keine Ahnung.
Würde mich freuen wenn mir jemand das erläutern könnte.
MfG Iwan
aha
ich habe in die pic16f628.inc reingeguckt, finde aber nichts
vergelichbares oder bin ich zu dämlich :-)
wo könnte man nachschauen was das bedeutet?
Startup Definiert den Start Vector wo der Mikrocontroller beim
Einschalten reinspringt.
INTVCT CODE:
Definiert den Interruptvektor
Main Setup Code:
Ist der Bereich wo das Hauptprogramm steht.
EE_Data Code 0x2100:
Gibt im EEPROM die gesamte Menge aller Bytes an bzw. diese
welche Reserviert werden.
Ich kenne mich mit PICs 0 aus da ich Atmels µcs Programmiere
aber ich denke das wird so passen. Assembler ist Assembler.
danke dir TrippleX kannst du auch verraten wo du dieses Wissen her hast,
ich würde gerne selber was darüber lesen. Ich glaube auch, dass das so
ist. Nur habe ich beispielsweise bei sprut.de gesehen, dass man direkt
Adressen eingibt wo jetzt nun z.B. der interrupt hinspring. Das wäre
dann die Anweisung: org 4
ich habe mir die Dateien, die zu deinem Projekt gehören, näher
angeschaut. Schau doch mal in das Linkescrip (16f628.lkr) an. Da findest
du deine Vektoren.
Wenn du mehr darüber wissen willst, dann schau dir doch den
GCC-Assembler bzw. Linker an. Ich habe mal einen Atmel ARM mit GCC
programmiert. Da hat mir GCC-Assembler/Linker-Doku weiter geholfen, die
Funktionsweise/Zusammenspiel der beiden zu verstehen, vor allem wenn du
den Startup-Code für deinen µC schreiben musst.
so
habe mir die 16f628.lkr genauer angeguckt und finde dort beispielsweise
den Eintrag: MAIN_SETUP niergends, es sind noch mehr einträge im
Quelltext der .asm Dateien wo dahinter immer CODE steht die aber nicht
in 16f628.lkr vorhanden sind. Aus dem Projekt lässt sich dennoch ohne
errors ein HEX-File erstellen?????
Ich versteh garnichts mehr.
Ich glaube du versuchst auf einen Schlag zu viel zu schlucken und
verschluckst dich natürlich dabei. Hast du den Zusammenhang zwischen
Assembler und Linker verstanden bzw. was das Linker-Skript für eine
Funktion hat und wie es aufgebaut ist? Verstehts du die
Assembler-Syntax, weißst du, was Sections sind?
Mein Ratschag, fang mit einem kleinen Programm an, dass du verstehts,
was es macht. Arbeite dich langsam nach vorne, kannst dir nebenbei auch
das Map-File dann anschauen.
Um mal auf deine Frage einzugehen, schau dir mal das PDF-File auf Seite
57 an. Da steht folgendes:
PGM CODE ;This is the beginning of the
;code section named PGM. It is
;a relocatable code section
;since no absolute address is
;given along with directive CODE.
Dein MAIN_SETUP ist nix anderes wie ein Code-Segment(Section), wo es
genau beginnt, das wird dann vom Linker erledigt. Wenn du dir das
dali.map anschaust, findest du folgende Zeilen:
Section Type Address Location Size(Bytes)
--------- --------- --------- --------- ---------
STARTUP code 0x000000 program 0x000002
INTVCT code 0x000004 program 0x00000c
.cinit romdata 0x000016 program 0x000004
MAIN_PROG code 0x000018 program 0x00018a
...
Hier taucht auch dein MAIN_SETUP auf, mit der Adresse, wo es im
Speicher steht und der Größe. Das ist nix anderes wie ein x-beliebiger
Name, was du dir frei wählen kannst.
@ ...
hast sicherlich recht mit zuviel auf einmal, habe aber leider keine Zeit
zum entspannend angehen lassen.
Danke dir für die Mühe durch deine Antworten werde ich immer auf den
richtigen Weg gelenkt, weiß mir leider nicht anderes zu Helfen als
gleichzeitig soviel wie möglich an Wissen aus so viel wie möglich
Quellen anzueignen. Bin echt auf euere Hilfe hier angewiesen, wenn ich
euch nerve, tut mir leid.
Werde mich weiter durchkämpfen und sicherlich weitere Fragen haben.
Der Linker-Skript hat die Funktion den Programmspeicher zu verwalten,
soweit ich es verstanden habe.
Die Assembler-Syntax verstehe ich einigermaßen auch(muss jedes mal
nachgucken was ein Befehl eigentlich macht), glaube ich zumindest.
Was Sections sind weiß ich jetzt nicht oder vielleicht kenne ich nur das
Wort nicht, aber schaue ich nach. Gucke mir auch die .map an.
MfG Iwan
wenn du dir das zweite Pdf anschaust, da ist es sehr gut beschrieben.
Eine Section ist nix anderes wie ein Segment. Ein Linker-Skript
beschreibt, wo welches Segment im Speicher liegt bzw. wo es
beginnt/endet. Es ist nämlich so, dass der Programmcode, initialisierte
bzw. nicht initialisierte Variablen nicht so einfach zusammen geschießen
werden, sondern sie werden jeder in seinem eigenen Segment getrennt
voneinander plaziert. Der Assembler übersetzt ein File in ein Objektfile
und der Linker "sortiert" das Ganze (siehe dali.map) zu einem
ausführbaren Code(Image).
Hi, ich habe hier noch mal in meiner Pdf-Sammlung geschaut und habe was
für MPLINK gefunden. Ist ein bißchen übersichtlicher, als wenn alles
zusammen in einem Dokument steht.
ich nutze den thread hier mal weiter :>
und zwar versuche ich mir grade assembler beizubringen "kann" bisher nur
C
erste frage/n :>
1
ldi R16, 0xFF
2
out DDRB, R16 ; Port B: Ausgang
3
4
ldi ZL, LOW(daten*2) ; Low-Byte der Adresse in Z-Pointer
5
ldi ZH, HIGH(daten*2) ; High-Byte der Adresse in Z-Pointer
6
7
lpm ; durch Z-Pointer adressiertes Byte
8
; in R0 laden
9
out PORTB, R0 ; an PORTB ausgeben
1. was hat es mit diesen R16 R17 usw. auf sich? mir ist klar das diese
register zum speichern von variablen genutzt werden.
ich meine irgendwo gesehen zuhaben das sie hardwareseitig existieren....
aber welcher art sind diese register? integer char....???
2. kann man die nennen wie man will? oder woher weiß man welche man
nutzen kann?
3. bzgl des pointers. gibt es nur den pointer Z? (ZL und ZH) oder kann
man den nennen wie man will?
außerdem betrachtet dieser pointer doch eine "fläche" nämlich den
datensatz daten...ich kannte pointer bisher immer so das man damit
einzelne inhalte in einem datensatz betrachtet :?
4. woher weiß lpm das ich die sachen nach R0 speichern will? ist das so
standard? das wäre ja noch kein großes ding aber, was wenn ich mehrere
pointer nutze?? woher weiß lpm dann welchen er nutzen soll?? oder wird
einfach immer der zuletzt definierte genutzt?
5. globales fragezeichen ^^"
gruß und danke für eure hilfe :}
> 1. was hat es mit diesen R16 R17 usw. auf sich? mir ist klar das diese> register zum speichern von variablen genutzt werden.> ich meine irgendwo gesehen zuhaben das sie hardwareseitig existieren....> aber welcher art sind diese register? integer char....???
Hängt von der Hardware ab -> Datenblatt. Die Interpretation liegt am
Kontext -> Datenblatt.
> 2. kann man die nennen wie man will? oder woher weiß man welche man> nutzen kann?
Die benennt man i.d.R. so, wie sie der Assembler erwartet. Wie der das
tut, das steht in dessen Datenblatt :-)
> 3. bzgl des pointers. gibt es nur den pointer Z? (ZL und ZH) oder kann> man den nennen wie man will?
Das hängt von der Hardware ab -> Datenblatt. Achja i.d.R. kann man
Register 'umbenennen' im Sinne von 'Aliasen'. Details liefert die Doku
zum Assembler :-)
> außerdem betrachtet dieser pointer doch eine "fläche" nämlich den> datensatz daten...ich kannte pointer bisher immer so das man damit> einzelne inhalte in einem datensatz betrachtet :?
Ein Pointer ist eine (Speicher)Adresse, nichts weiter. Die
Interpretation obliegt dem Programmierer :-)
> 4. woher weiß lpm das ich die sachen nach R0 speichern will? ist das so> standard? das wäre ja noch kein großes ding aber, was wenn ich mehrere> pointer nutze?? woher weiß lpm dann welchen er nutzen soll?? oder wird> einfach immer der zuletzt definierte genutzt?
Das steht im Datenblatt in der Kategorie 'lpm' :-) Und obs
Hardwareunterstützung für mehr Zeiger gibt ebenfalls :-) Im Großen und
Ganzen kann man aber sagen: Je mehr RISC desto unwahrscheinlicher, je
mehr CISC desto wahrscheinlicher.
> 5. globales fragezeichen ^^"
Nicht verzagen, Doku lesen. Vorzugsweise vollständig, auch wenn das u.U.
ein paar hundert Seiten sind. Falls es weniger ist, dann hat man die
falsche Doku erwischt.
Zum Einstieg ist es sicher auch nicht verkehrt, die wichtigen Teile
auszudrucken und altmodisch mit schmalen Farbspuren zu kennzeichnen ;-)
HTH
gast schrieb:
> ich nutze den thread hier mal weiter :>
Aha, Du benutzt also auch nen PIC und hast Fragen zum Linker.
Wenn nicht, dann laß das Hijacken und mach gefälligst nen eigenen Thread
auf.
Hijacken bringt bestenfalls Zufallstreffer, aber dafür den Thread
gehörig durcheinander.
Peter
@ Iwan Ne
weiss nich obs dir weiterhilft oder ob du's schon kennst
aber beste Seite um nen Einstieg in Pic und Assembler zu kriegen fand
ich immer www.Sprut.de.
viel Erfolg
Felix
kann es sein das man sowas in C garnicht hat?
werden die nur dafür definiert, damit das programm zu einer funktion
zurückfindet?
denn wenn ich das ganze stackpointer zeugs auskommentiere verschluckt er
sich beim rcall befehl...
was mich außerdem auch noch stutzig macht ist:
[code]
inc r16 ;Datenwert erhöhen
[code]
wenn r16 als stackpointer genutzt wird...oder sind im register dafür
extra bits freigestellt?
dann kann man doch nicht einfach mit inc r16 das register neubeschreiben
dadurch würde doch der pointer beschädigt :?
da es aber funktioniert....was verstehe ich hier falsch?
was ich auch schon öfter gesehen habe und mir immer noch schleierhaft
ist...
die warteschleife, warum steht da als label wait: und direkt darunter
wait1:?
gruß
gast schrieb:
> ich bins nochmal :/
Aha
FAng mal hier zu lesen an.
http://www.mikrocontroller.net/articles/AVR-Tutorial
Das erste Kapitel kannst du überspringen und gleich zu I/O Grundlagen
weitergehen.
Un dbesorg dir bei Atmel das Datenblatt zu deinem Prozessor sowie die
Befehlscodereferenz
> ich werde nicht schlau aus diesen stackpointern>
1
> start: ldi r16,low(ramend)
2
> ldi r17,high(ramend) ;Adresse vom RAM-Ende laden
3
> out spl,r16 ;Stackpointer auf
4
> out sph,r17 ;RAM-Ende setzen
5
>
>> kann es sein das man sowas in C garnicht hat?
Doch der ist auch dort vorhanden. Nur brauchst du dich als
C-Programmierer nicht darum kümmern.
> denn wenn ich das ganze stackpointer zeugs auskommentiere verschluckt er> sich beim rcall befehl...
Du lernst falsch. Einfach sinnlos ausprobieren führt nicht zum Ziel.
> [code]> inc r16 ;Datenwert erhöhen> [code]>> wenn r16 als stackpointer genutzt wird...
Wer sagt denn, dass r16 der Stackpointer ist?
> die warteschleife, warum steht da als label wait: und direkt darunter> wait1:?
1) ist das nicht direkt darunter, sondern da sind ein paar Anweisungen
dazwischen
2) Warum soll sich der Programmierer nicht mehrere Labels definieren,
wenn er das möchte und es ihm sinnvoll erscheint, weil er einen Sprung
genau auf diese Stelle machen möchte.
gast schrieb:
> danke gast> mir war nicht klar das das ganze SO hardware nah ist :)
Lass es mich mal so ausdrücken:
Noch hardwarenäher geht nur indem du den Chip umätzt.
>2) Warum soll sich der Programmierer nicht mehrere Labels definieren,>wenn er das möchte und es ihm sinnvoll erscheint, weil er einen Sprung>genau auf diese Stelle machen möchte.
ok, wenn mehr nicht dahintersteckt ists ja in ordnung ^^
>Doch der ist auch dort vorhanden. Nur brauchst du dich als>C-Programmierer nicht darum kümmern.
scho klar, so war das gemeint...das man nichts unwichtiges tippt ist ja
logisch ^^
war blöd vormuliert
an dem avr tutorial bin ich natürlich dran...nur manchmal sind da
sprünge drin bei denen klemmt es dann etwas...
mir ist z.b. nicht wirklich klar warum man immer high und low hat (bei
pointern)
ich habe das zwar so verstanden das sie aus zwei bits bestehen aber
warum das so ist.....ka..
>Wer sagt denn, dass r16 der Stackpointer ist?
vermutlich niemand...
ich habe das nur so verstanden
mit ldi läd man doch hier etwas in r16... und normalerweise das was
hinter dem komma steht.. :?
1
> start: ldi r16,low(ramend)
2
> ldi r17,high(ramend) ;Adresse vom RAM-Ende laden
gast schrieb:
> an dem avr tutorial bin ich natürlich dran...nur manchmal sind da> sprünge drin bei denen klemmt es dann etwas...
OK. Das kommt vor.
Wir sind ja auch daran interessiert, das Tutorial zu verbessern.
> mir ist z.b. nicht wirklich klar warum man immer high und low hat (bei> pointern)
Weil eine Speicheradresse aus 16 Bit besteht, die Register aber nur 8
Bit breit sind. Also muss man Manipulationen, die 16 Bit betreffen, in 2
Schüben machen. Einmal mit den höherwertigen 8 Bit, einmal mit den 8
niederwertigen Bits.
> ich habe das zwar so verstanden das sie aus zwei bits bestehen aber> warum das so ist.....ka..
Nicht 2 Bits.
> mit ldi läd man doch hier etwas in r16... und normalerweise das was> hinter dem komma steht.. :?
Ja schon.
Aber was passiert denn danach ...
Danach werden die Werte von r16/r17 in den tatsächlichen Stackpointer
übertragen.
1
out spl,r16 ;Stackpointer auf
2
out sph,r17 ;RAM-Ende setzen
und damit sind die Register r16 und r17 wieder für andere Aufgaben frei.
sph/spl ist der Stackpointer, nicht r16/r17. r16/r17 sind nur die
Transportregister um die gewünschten Werte in den Stackpointer zu
transportieren (weil es dafür keinen direkten Befehl gibt ... siehe
Datenblatt)
gast schrieb:
> an dem avr tutorial bin ich natürlich dran...nur manchmal sind da> sprünge drin bei denen klemmt es dann etwas...> mir ist z.b. nicht wirklich klar warum man immer high und low hat (bei> pointern)
Weil ein Register 1 Byte enthält, Du aber zum Adressieren eines
Adrssraumes von >256 Bytes (bzw. Words) 2 Bytes benötigst. Dazu werden 2
benachbarte Register zu einem Indexregister (=Pointer) zusammengesetzt.
Eines davon beinhaltet den High-Teil und das andere den Low-Teil der
Adresse.
> ich habe das zwar so verstanden das sie aus zwei bits bestehen aber> warum das so ist.....ka..
2 Bytes, nicht Bits
>>Wer sagt denn, dass r16 der Stackpointer ist?> vermutlich niemand...> ich habe das nur so verstanden> mit ldi läd man doch hier etwas in r16... und normalerweise das was> hinter dem komma steht.. :?
r16 und r17 werden in Deinem Beispiel nur als Zwischenstation für die
Adressinformation benutzt. Der Assembler kann in die Speicherstellen des
Stackpointers keine Werte direkt eintragen, dazu muß man den Umweg über
die Register gehen.
1
>> start: ldi r16,low(ramend)
2
>> ldi r17,high(ramend) ;Adresse vom RAM-Ende laden
Ja, aber das Entscheidende fehlt hier (ist aber in Deinem Beispiel oben
enthalten):
1
>> out spl,r16 ;Stackpointer auf
2
>> out sph,r17 ;RAM-Ende setzen
Hier werden die Inhalte der Register in den Stackpointer geladen.
Anschließend sind die beiden Register wieder für andere Aufgaben frei,
behalten aber ihren Inhalt noch.
Reinhard
>Nicht 2 Bits.
ist schon spät ^^"
bytes natürlich sorry
>Danach werden die Werte von r16/r17 in den tatsächlichen Stackpointer>übertragen.> out spl,r16 ;Stackpointer auf> out sph,r17 ;RAM-Ende setzen>und damit sind die Register r16 und r17 wieder für andere Aufgaben frei.>sph/spl ist der Stackpointer, nicht r16/r17. r16/r17 sind nur die>Transportregister um die gewünschten Werte in den Stackpointer zu>transportieren (weil es dafür keinen direkten Befehl gibt ... siehe>Datenblatt)
danke dann sind mir die beiden spalten jetzt auch klar :)
da muss ich mich echt erst dran gewöhnen :/ in c ballert man immer alles
schön sofort dahin wo man es haben will (jedenfalls wirkt es so)
>Wir sind ja auch daran interessiert, das Tutorial zu verbessern.
bin immer wieder begeistert von der jetzt schon vorhandenen qualität des
wikis und vor allem des forums!
und super ist auch das ihr keine optischen emoticons aktiviert habt :)
d/^_^\b
gast schrieb:
> danke dann sind mir die beiden spalten jetzt auch klar :)> da muss ich mich echt erst dran gewöhnen :/ in c ballert man immer alles> schön sofort dahin wo man es haben will (jedenfalls wirkt es so)
Du gibst auch einen Brief auf und irgendwie 'magisch' gelangt er an sein
Ziel. Die Mechanismen die gahinter stecken, siehst du auch nicht und du
musst dich auch nicht darum kümmen.
ALs Assemblerprogrammierer bist du aber Briefschreiber,
Verteilerzentrale, Postflugzeugführer und Zusteller in Personalunion.
@Karl heinz Buchegger (kbuchegg) (Moderator)
Schöner Vergleich :-)
@gast
Was Karl Heinz sagen will (sorry Karl Heinz, daß ich Dich
interpretiere), ist, dass Du beim Programmieren mit Assembler für jedes
Detail selbst zuständig bist, bei Hochsprachen wird Dir vieles vom
Compiler abgenommen.
Gutes Beispiel ist der Stack. Der dient zum Speichern von
Rücksprungadressen und zum Retten von Registerinhalten. Bei den
Hochsprachen kümmert sich der Compiler komplett um dessen Organisation
und Nutzung. Beim Assembler bist Du dafür zuständig. Du mußt den Stack
erst mal initialisieren, d.h. dem Stackpointer sagen, ab welcher Adresse
er seine Daten ablegen darf. Dazu mußt Du Dich im Datenblatt
informieren, bei welchen Adressen Du den RAM findest (dort wird der
Stack platziert). Du mußt Dir über die Arbeitsweise des Stack klar sein,
er legt das zu speicherde Byte auf der aktuellen Adresse ab und zählt
dann eine Adresse runter. Beim Lesen ist es umgekehrt, er erhöht seine
Adresse und liest das dort liegende Byte. D.h. der Stackpointer braucht
unterhalb seiner Initialisierungsadresse freien RAM. Deshalb wird er
normalerweise auf die höchste RAM-Adresse initialisiert. Ausnahmen nicht
ausgeschlossen.
Dann bei der Verwendung selbst darauf achten, daß alle eingelagerten
Daten vollständig und in der richtigen Reihenfolge wieder entnommen
werden. Sonst droht Stacküberlauf und Dein Programm stürzt ab. D.h. Call
und Ret bzw. Push und Pop richtig schachteln.
Es gibt noch viele andere Sachen, die man beim Programmieren mit
Assembler beachten muß. Die wichtigsten Informationsquellen sind dabei
das Datenblatt des Prozessors, die Befehlsbeschreibung und die Anleitung
für den benutzten Assembler. Für den allseits beliebten ATmega8 mal die
Links zu den Infos:
Datenblatt
http://atmel.com/dyn/resources/prod_documents/doc8159.pdf
Instruction Set
http://atmel.com/dyn/resources/prod_documents/doc0856.pdf
wobei die implementierten Befehle für den verwendeten Prozessor am Ende
dessen Datenblatts aufgeführt sind.
Zum Programmieren in Assembler bietet sich das "AVR Studio 4" an:
http://atmel.com/forms/software_download.asp?fn=dl_AvrStudio417Setup.exe
ist gratis, mußt Dich aber registrieren. Die dort enthaltene Hilfe ist
recht umfangreich, die Befehle sind dort auch alle noch mal erklärt.
Ich wünsche Dir noch viel Erfolg beim Einarbeiten. Und immer dran
denken:
Beim Assembler kennst Du noch jedes Bit persönlich :-)
Reinhard
danke für den ausführlichen post :)
das meiste ist mir davon aber schon klar
ich habe vor einiger zeit schon einmal angefangen atmel prozessoren zu
programmieren aber in C, da ich da noch ganz gut drin bin durchs
studium...
je mehr ich mich aber damit beschäftigt habe, je mehr wurde mir
persönlich klar C und µCs ist für mich nicht so das wahre...atmel
scheint das ja auch so zu sehen :P
daher die idee das ganze noch mal von vorn zulernen...glücklicherweise
erfindet man bei programmiersprachen ja nicht das rad neu, so dass das
ganze zügig gehen sollte
habe heute zum reinfinden erstmal mit hilfe der im wiki stehenden lcdlib
eine eigene lcd libary geschrieben...
und in C kann man echt nicht auf den stack zugreifen? finde das
mittlerweile recht nützlich.
hat es eigentlich geschwindigkeitsvorteile, wenn man den stack als
variable nutzt?
atm nutze ich es nur zum variablen sichern....da der pointer aber immer
auf einen freien stack slot zeigt kam mir der gedanke das es evtl.
schneller ist dort als in einem register zuspeichern :?
davon abgesehen finde ich den assembler syntax deutlich schöner und kein
nerviges ";" am ende jeder zeile :D
gast schrieb:
> und in C kann man echt nicht auf den stack zugreifen? finde das> mittlerweile recht nützlich.> hat es eigentlich geschwindigkeitsvorteile, wenn man den stack als> variable nutzt?
Genau dafür benutzt dein C-Compiler zb den Stack: Um dort lokale
Variablen anzulegen :-)
> auf einen freien stack slot zeigt kam mir der gedanke das es evtl.> schneller ist dort als in einem register zuspeichern :?
???
Entweder du drückst dich jetzt ungeschickt aus, oder du hast nicht
verstanden, was es mit den Registern auf sich hat.
> davon abgesehen finde ich den assembler syntax deutlich schöner und kein> nerviges ";" am ende jeder zeile :D
Dafür musst du dich um jeden Scheiss selber kümmern
int main()
{
int y;
DDRA = 0xFF;
while( 1 ) {
y = PIND;
PORTA = y * PINB / 3;
}
}
Schreib diesen 5-Zeiler mal in Assembler, so dass er exakt das gleiche
Verhalten hat. Danach wirst du die "nervigen ';'" nur noch als Peanuts
ansehen :-)
PS:
> habe heute zum reinfinden erstmal mit hilfe der im wiki stehenden> lcdlib eine eigene lcd libary geschrieben...
Warum blos nehme ich dir das nicht ab :-)
>???>Entweder du drückst dich jetzt ungeschickt aus, oder du hast nicht>verstanden, was es mit den Registern auf sich hat.
ich stelle mir das als lange liste aus registern vor...der stack füllt
diese von rechts und ich idealerweise von links
>Schreib diesen 5-Zeiler mal in Assembler, so dass er exakt das gleiche>Verhalten hat. Danach wirst du die "nervigen ';'" nur noch als Peanuts>ansehen :-)
glaub ich dir gerne
>Warum blos nehme ich dir das nicht ab :-)
ja, warum bloß?
aber wo wir gerade dabei sind, bei einer sache harkt es.. und zwar beim
auslesen von strings per zeiger
mir ist nicht 100% klar warum das so funktioniert wie es funktioniert
zitat von irgendwo
>Für das Lesen aus dem Programmspeicher gibt es nur den Zeiger Z und den >Befehl
LPM. Er lädt das Byte an der Adresse Z in das Register R0.
hier wird aber direkt nach r16 gespeichert oder nicht :?
2. fängt z IMMER bei 0 an zuzählen? könnte doch auch sein das da zufällt
eine zahl drin steht und dann fängt er mitten im string an zuzählen :?
Hi
>Er lädt das Byte an der Adresse Z in das Register R0.>hier wird aber direkt nach r16 gespeichert oder nicht :?
Wenn du wirklich in Assembler programmieren willst (mach ich selbst
ausschließlich), solltest du dir wenigstens mal das Instruction Set zu
Gemüte führe. LPM nach r0 war bei den ersten AVRs die alleinige
Möglichkeit. Beiden neueren geht das für jedes Register.
MfG Spess
gast schrieb:
>>???>>Entweder du drückst dich jetzt ungeschickt aus, oder du hast nicht>>verstanden, was es mit den Registern auf sich hat.>> ich stelle mir das als lange liste aus registern vor...der stack füllt> diese von rechts und ich idealerweise von links
[ ] Du hast es verstanden
[x] Du hast nicht verstanden, was ein Register ist.
>>Warum blos nehme ich dir das nicht ab :-)> ja, warum bloß?
Weil du hier bei den simpelsten Dingen die abenteuerlichsten Fehler
machst. Du hast vielleicht die LCD-Funktionen abgeschrieben. Aber du
hast sie nicht selbst geschrieben. Malen nach Zahlen hat mit dem was ein
echter Maler tut nicht sehr viel gemeinsam.
>>Für das Lesen aus dem Programmspeicher gibt es nur den Zeiger Z und den >Befehl> LPM. Er lädt das Byte an der Adresse Z in das Register R0.> hier wird aber direkt nach r16 gespeichert oder nicht :?
Wo?
> 2. fängt z IMMER bei 0 an zuzählen?
z enthält den Wert, den du reinladest.
> könnte doch auch sein das da zufällt> eine zahl drin steht und dann fängt er mitten im string an zuzählen :?>> [code]> lcd_flashstr:> push r16> push ZH> push ZL>>> flashstr1:> lpm r16, z+ <<<<<<<<< HIIIIIIIER
Datenblatt/Instruction Set lesen.
Es gibt mehrere Varianten dieses Ladebefehls.
>solltest du dir wenigstens mal das Instruction Set zu
Gemüte führe
omfg ist das viel o.O
gibt es denn nichts einfaches auf dieser welt :lol:
>LPM nach r0 war bei den ersten AVRs die alleinige>Möglichkeit.
ich hatte das mehrfach gelesen deshalb als richtig abgespeichert :/
>Wo?
da!
>lpm r16, z+ <<<<<<<<< HIIIIIIIER