Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage zu Assembler


von Wanja N. (dasalphatier)


Lesenswert?

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

von Wanja N. (dasalphatier)


Lesenswert?

hat denn niemand sowas schon mal im Quelltext gesehen?

von Kay (Gast)


Lesenswert?

Hallo, so etwas habe ich noch nie gesehen

von ... (Gast)


Lesenswert?

stell doch mal das File hier rein.

von Wanja N. (dasalphatier)


Angehängte Dateien:

Lesenswert?

hier nochmal das mainFile aus dem Projekt. Ich vermute dass es auch 
irgendwas mit mplab zutun hat. Danke schon mal voraus für die Mühe.

von günter (Gast)


Lesenswert?

hi das sieht nach Defines aus wie sie normalerweise in der pic16f628.inc 
stehen also im linker script

von Wanja N. (dasalphatier)


Lesenswert?

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?

von TrippleX (Gast)


Lesenswert?

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.

von Wanja N. (dasalphatier)


Lesenswert?

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

von ... (Gast)


Lesenswert?

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.

von Wanja N. (dasalphatier)


Lesenswert?

vielen dank für die Antwort
blicke noch nicht ganz durch aber werde mir die Sachen in den nächsten 
Tagen mal genauer ansehen.

von ... (Gast)


Angehängte Dateien:

Lesenswert?

schau hier rein

von Wanja N. (dasalphatier)


Lesenswert?

jo dankeschön
werde ich tun, 300 Seiten auf englisch, wie ich das liebe :-)

von Wanja N. (dasalphatier)


Lesenswert?

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.

von ... (Gast)


Lesenswert?

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.

von ... (Gast)



Lesenswert?

hier noch mal ein älters User' Guide, sieht auf den ersten Blick 
verständlicher aus.

von Wanja N. (dasalphatier)


Lesenswert?

@ ...
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

von ... (Gast)


Lesenswert?

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).

von Wanja N. (dasalphatier)


Lesenswert?

aha
es wird langsam klarer danke nochmal.

von ... (Gast)


Angehängte Dateien:

Lesenswert?

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.

von gast (Gast)


Lesenswert?

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 :}

von Name: (Gast)


Lesenswert?

> 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

von Peter D. (peda)


Lesenswert?

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

von gast (Gast)


Lesenswert?

danke gast
mir war nicht klar das das ganze SO hardware nah ist :)

von Felice D. (flexbex)


Lesenswert?

@ 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

von gast (Gast)


Lesenswert?

ich bins nochmal :/
1
.include "m8def.inc"      ;Definitionsdatei laden
2
.cseg          ;Beginn eines Code-Segmentes
3
.org 0          ;Startadresse = 0
4
;
5
start:  ldi  r16,low(ramend)
6
  ldi  r17,high(ramend)  ;Adresse vom RAM-Ende laden
7
  out  spl,r16      ;Stackpointer auf
8
  out  sph,r17      ;RAM-Ende setzen
9
  ldi  r16,0b00000001    ;PortB: PB0 auf Ausgang
10
  out  ddrb,r16    ;setzen
11
  clr  r16      ;Datenwert für Ausgabe setzen
12
;
13
loop:  out  portb,r16    ;Daten an PortB ausgeben
14
  rcall  wait      ;Warteschleife aufrufen
15
  inc  r16      ;Datenwert erhöhen
16
  rjmp  loop      ;Programmschleife neu beginnen
17
;
18
;  Warteschleife (ungefähr 500ms)
19
;
20
wait:  ldi  r19,10      ;r19,r18,r17 -> 3-Byte-Zähler
21
  clr  r18      ;höchstes Byte = 10, restliche
22
  clr  r17      ;Bytes = 0
23
wait1:  dec  r17      ;niedrigstes Byte -1
24
  brne  wait1      ;0 erreicht? nein -> Schleife
25
  dec  r18      ;mittleres Byte -1
26
  brne  wait1      ;0 erreicht? nein -> Schleife
27
  dec  r19      ;höchstes Byte -1
28
  brne  wait1      ;0 erreicht? nein -> Schleife
29
  ret        ;Schleifenende, Rückkehr
30
;
31
.eseg          ;Beginn eines EEPROM-Segmentes


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

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ß

von Karl H. (kbuchegg)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

von gast (Gast)


Lesenswert?

>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

von Karl H. (kbuchegg)


Lesenswert?

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)

von Reinhard R. (reirawb)


Lesenswert?

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

von gast (Gast)


Lesenswert?

>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

von Karl H. (kbuchegg)


Lesenswert?

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.

von Reinhard R. (reirawb)


Lesenswert?

@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

von gast (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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 :-)

von gast (Gast)


Lesenswert?

>???
>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 :?
1
lcd_flashstr:  
2
push r16
3
push ZH
4
push ZL
5
        
6
        
7
flashstr1:  
8
lpm r16, z+  <<<<<<<<< HIIIIIIIER
9
cpi r16, 0
10
breq flashstr2
11
rcall lcd_data
12
rjmp flashstr1
13
  
14
flashstr2:  
15
pop ZL  
16
pop ZH
17
pop r16
18
ret


gruß

von spess53 (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von gast (Gast)


Lesenswert?

>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

von spess53 (Gast)


Lesenswert?

Hi

>ich hatte das mehrfach gelesen deshalb als richtig abgespeichert :/

Ist ja auch nicht falsch.

 lpm  -> r0
 lpm r16,Z (+)  -> r16

MfG Spess

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
Noch kein Account? Hier anmelden.