Forum: Mikrocontroller und Digitale Elektronik Assembler Programmcounter


von Felix (Gast)


Lesenswert?

Hallo liebe Gemeinde,

ich programmiere auf einem Atmega324 in Assembler und habe da letztens
im Netz irgendwo her eine interessante Variante gefunden um Sprungweiten
zu definieren.

In dem Beispiel:

brne  pc+2

ist das Sprungziel statt einem Label/Sprungmarke einfach der aktuelle
stand des Programmcounters+2...d.h der nachfolgende Befehl wird nicht
ausgeführt,wenn die Bedingung nicht wahr ist.
Damit kann man z.B. sehr kompakt Bedingungen auswerten....allerdings
ist mir aufgefallen, dass die Sprungweite nicht gleich der Anzahl der
zu überspringenden Befehle ist!?
Ich hab die Vermutung das dies an der unterschiedlichen Länge der Op-
codes liegt, wenn diese in den Flash abgelegt werden.

Bei folgenden Beispiel sollte man annehmen das der Sprung auf "rcall 
bedingung_nicht_wahr" erfolgt,allerdings landet man promt auf "ret",
weshalb man hier eine Sprungweite von pc+5 angeben müsste.

brne  pc+4
ldi   r17,1
sts   status,r17
ret
rcall bedingung_nicht_wahr

Hingegen funktioniert dieses Beispiel gut:

brne  pc+2
ret
rcall bedingung_nicht_wahr

Vielleicht hat sich jemand schon näher damit befasst und kann mir ein 
paar
Tips geben,um die Sprungweite in jedem Fall genau berechnen zu können?

Vielen Dank fürs lesen!!!

von MaWin (Gast)


Lesenswert?

Das ist nicht interessant, sondern einfach nur unübersichtlicher 
bullshit, du merkst selbst wie du damit durch unterschiedliche 
Instruktiondlängen in die Bedroullie kommst.

Schreibe am Ziel (also ggf. hinter der nächsten Instruktion) ein Label 
(Sprungmarke) hin und nenne die in deinem Branch (Sprunganweisung) und 
alles wird gut.

Man wird nicht zum Held bloss weil man partout alles schlechter machen 
will als Millionen andere Leute.

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Jaja, das musste man früher mal so machen, als die Assembler noch keine 
Forward Labels konnten - und niemand möchte das wiederhaben. Jeder 
moderne 2-Pass Assembler kommt auch mit Forward Labels klar und du musst 
nicht auswendig wissen, wieviele Bytes jeder einzelne Befehl hat.

: Bearbeitet durch User
von Felix (Gast)


Lesenswert?

Hallo MaWin,

da hast Du sicher Recht, ich hab mich immer sehr schwer sinnige Namen
für die Label zu vergeben,fand es ehrlich gesagt gut eine Sprungweite
anzugeben...allerdings geht es ja eben auch oft in die Hose im Gegensatz
zu eindeutigen Sprungmarken ;-)

Danke für Deine investierte Zeit :)

Felix

von Karl H. (kbuchegg)


Lesenswert?

Felix schrieb:

> Tips geben,um die Sprungweite in jedem Fall genau berechnen zu können?

Das Instruction Set Summary könnte das
* die Adresse wird als Wortadresse berechnet
* jeder deiner Befehle belegt 1 Wort, mit Ausnahme vom
* STS, der belegt 2 Wörter

Wie man alles unschwer am Assembler Listing File erkennen kann.

ABER:
MaWin hat recht. Das ist alles hauptsächlich dazu geeignet sich 
möglichst unelegant ins Knie zu schiessen. Oder willst du wirklich in 
einem Assembler Programm alle Adressen bei allen Branches kontrollieren, 
ob sie sich geändert haben, nur weil du irgendwo einen Befehl dazu 
gemacht hast?
Sei froh, dass diese Zeit vorbei ist und jemand vor langer, langer Zeit 
die glorreiche Idee hatte, dass man Sprungziele auch mit einem Namen 
benennen kann und sich der Assembler den Offset auch selbst ausrechnen 
kann. Die Zahl der wilden Programmfehler ist dadurch von einem Tag auf 
den anderen drastisch gefallen.

von Felix (Gast)


Lesenswert?

@ Matthias

Ok, dann hab ich jetzt etwas dazu gelernt :)
Danke Euch!!!

von S. Landolt (Gast)


Lesenswert?

Es sind vier Befehle, die zwei Worte belegen: sts, lds, jmp und call. 
Die kann man sich merken, und das ist auch nicht das Problem. Das 
Problem entsteht, wie bereits beschrieben, bei Programmänderungen; 
Befehle herauszunehmen oder hinzuzufügen ohne genaue Kontrolle der 
Programmumgebung führt zu stundenlanger Fehlersuche. Andererseits - 
ebendies, eine genaue Kontrolle des zu ändernden Bereichs, ist bei 
Assemblerprogrammierung zwingend; eine Frage der Disziplin.

von Klaus (Gast)


Lesenswert?

Ja. Ja. Es ist Wochenende und wieder hat einer das geschnittene Brot 
erfunden.

von Jan H. (j_hansen)


Lesenswert?

Felix schrieb:
> ich hab mich immer sehr schwer sinnige Namen
> für die Label zu vergeben,fand es ehrlich gesagt gut eine Sprungweite
> anzugeben

Wie hat Herr Karlton so schön gesagt:"There are only two hard things in 
Computer Science: cache invalidation and naming things."

Weil die Namensfindung schwierig ist, gleich gar keine Namen mehr zu 
vergeben ist ein "kreativer" Ansatz :)

von Georg (Gast)


Lesenswert?

Felix schrieb:
> ist das Sprungziel statt einem Label/Sprungmarke einfach der aktuelle
> stand des Programmcounters+2

Das ist auch keineswegs ein anderer Befehl, JMP PC+Dist ist genau das 
Gleiche wie JMP Label, nur rechnet beim Label der Assembler den Abstand 
selbst aus, und zwar immer richtig, sofern der Sprung überhaupt möglich 
ist. Man kann also nicht das geringste einsparen und verzichtet nur 
völlig unnötig auf Bedienkomfort, ganz abgesehen davon, dass man ein 
riesiges Fass an zusätzlichen Fehlern aufmacht (Gilt natürlich nicht für 
die Poster hier, die niemals einen Fehler machen und alle Befehle 
inklusive Byte- und Zyklenzahl im Kopf haben).

Georg

von Felix (Gast)


Lesenswert?

@Klaus

Was hat das mit dem Wochenende zutun?
Die Woche neigt sich gerade zum WE,wir sind also noch in der Woche und
Neugier zu teilen,dabei vielleicht altes zu erfahren ist keine schlechte 
Sache.
Oftmals kann man durch das Gesamtbild besser Probleme lösen,man nennt
dieses Gesamtbild auch Erfahrung...
Viele User haben mir diese weitergereicht,dafür bin ich sehr dankbar!
Ich weis nicht ob Du das verstehen kannst, aber ich erweitere meine
Sichtweise gerne, denn ich möchte nicht zu den Leuten gehören deren
Horizont einen Radius von 0 hat und diesen ihren Standpunkt nennen :)

Schönen Freitag Abend noch ;-)

von S. Landolt (Gast)


Lesenswert?

Ihn dünkt', er sähe einen Sprung,
  dahinter stand + 10.
Er guckt' noch mal und merkt', es war,
  auch noch "pc" zu sehn.
"Das, freilich, geht so nicht," sprach er,
  "hier muss ein Label stehn."

von Peter D. (peda)


Lesenswert?

Felix schrieb:
> ich hab mich immer sehr schwer sinnige Namen
> für die Label zu vergeben

Wenn Du Labels mehrfach vergibst, kriegst Du das von Assembler 
angemeckert, also kein Problem.

Oder nimm den GAS des AVR-GCC, da kannst Du dann z.B. nach 1b, 2f usw. 
springen.

https://sourceware.org/binutils/docs/as/Symbol-Names.html#Symbol-Names
Siehe Local Labels

von S. Landolt (Gast)


Lesenswert?

> Oder willst du wirklich in einem Assembler Programm alle
> Adressen bei allen Branches kontrollieren, ob sie sich
> geändert haben, nur weil du irgendwo einen Befehl dazu
> gemacht hast?

Um Missverständisse auszuschließen: es geht nicht um entweder/oder, 
sondern um sowohl/als auch. Normale Sprünge wird man immer mit Label 
ausführen, ein pc +- n ist nur sehr lokal beherrschbar, vielleicht mit 
n<6, spätestens bei 10 wird es schwierig.
Aber ich bin wie Felix der Meinung, dass beim 'Auswerten kompakter 
Bedingungen' die Vielzahl der Label zu einer gewissen 
Unübersichtlichkeit führt.

von Fpgakuechle K. (Gast)


Lesenswert?

Macht der ARM Cortex M4 ebenfalls:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0439b/CHDDIGAC.html

R15 ist identisch zum programm counter, das reduziert den Befehlssatz, 
da kein extra JMP implementiert werden muß. Durch die bedingte 
Ausführung der meisten  ARM Befehle werden so bedingte Sprünge "im 
vorbeigehen" implementiert.

MfG,

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Felix schrieb:
> brne  pc+4
> ldi   r17,1
> sts   status,r17
> ret
> rcall bedingung_nicht_wahr

 Wieso das ubersichtlicher und einfacher als Beispiel unten sein soll,
 wird mir niemals klar sein:
1
      brne    b_false
2
      ...
3
      ...
4
      ret
5
b_false:
6
      rcall   bedingung_nicht_wahr


S. Landolt schrieb:
> Aber ich bin wie Felix der Meinung, dass beim 'Auswerten kompakter
> Bedingungen' die Vielzahl der Label zu einer gewissen
> Unübersichtlichkeit führt.

 Label trennt man normalerweise mit einer Leerzeile ( neues Block )
 oder schreibt nur diese in eine Zeile mit CR/LF.
 Nur weil man keine Label in seinem Programm hat, wird es bestimmt
 nicht ubersichtlicher.
 Und wenn man ein bisschen weiter als LED-blinken kommt, wird es mit
 bedingten Sprungen von 2,3 oder sogar 60 Bytes nix. Und solltest du
 in deinem Beispiel irgendetwas andern, z.B. r17 retten (PUSH), wird
 es schon kritisch.
 Vielleicht ist das die einzige Stelle mit einem solchen Sprung - aber
 was ist wenn du weiter oben noch einen Sprung hast ?

Felix schrieb:
> Ich weis nicht ob Du das verstehen kannst, aber ich erweitere meine
> Sichtweise gerne, denn ich möchte nicht zu den Leuten gehören deren
> Horizont einen Radius von 0 hat und diesen ihren Standpunkt nennen :)

 Wie man mit so etwas unsinnigem sein Horizont erweitern kann, ist mir
 nicht ganz klar, aber wenn das trotzdem so ist, braucht dein Horizont
 wirklich dringend eine Erweiterung, nur hast du die falsche Richtung
 gewahlt...

: Bearbeitet durch User
von spess53 (Gast)


Lesenswert?

Hi

> oder schreibt nur diese in eine Zeile mit CR/LF.

Wo steht das? Bei mir sieht eine Assemblerzeile mit Label so

Label:     Befehl        :Kommentar

aus. Ich frag mich immer warum das alles an den linken Rand geklemmt 
werden muss. Stammt wahrscheinlich aus den Zeiten mit Monitoren mit 20 
Zeichen/Zeile.

Obwohl, zu DDR-Zeiten gab es schon für Assembler Formulare bei denen 
alles in einer Zeile war.

MfG Spess

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

spess53 schrieb:
> Wo steht das? Bei mir sieht eine Assemblerzeile mit Label so
>
> Label:     Befehl        :Kommentar

 Dann muss dein Compiler entweder sehr tolerant oder sehr schlau sein.

von spess53 (Gast)


Lesenswert?

HI

>Dann muss dein Compiler entweder sehr tolerant oder sehr schlau sein.

Wieso? Wird vom AVR-Assembler problemlos Assembliert:

http://www.mikrocontroller.net/attachment/highlight/43220

MfG Spess

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

spess53 schrieb:
> HI
>
>>Dann muss dein Compiler entweder sehr tolerant oder sehr schlau sein.
>
> Wieso? Wird vom AVR-Assembler problemlos Assembliert:
>
> http://www.mikrocontroller.net/attachment/highlight/43220
>
> MfG Spess

spess53 schrieb:
> Label:     Befehl        :Kommentar
                           ^
                           |
  Doppelpunkt auch ?

von Fpgakuechle K. (Gast)


Lesenswert?

Felix schrieb:

> ich programmiere auf einem Atmega324 in Assembler und habe da letztens
> im Netz irgendwo her eine interessante Variante gefunden um Sprungweiten
> zu definieren.
>
> In dem Beispiel:
>
> brne  pc+2
>
> ist das Sprungziel statt einem Label/Sprungmarke einfach der aktuelle
> stand des Programmcounters+2...d.h der nachfolgende Befehl wird nicht
> ausgeführt,wenn die Bedingung nicht wahr ist.


> Vielleicht hat sich jemand schon näher damit befasst und kann mir ein
> paar
> Tips geben,um die Sprungweite in jedem Fall genau berechnen zu können?

Moin ,

die Frage bezieht sich auf unterschiedlich arten von Sprüngen resp 
Sprugzielen:
1) absolut
2) relativ

Bei nummer 1 ist im sprungbefehl die Zieladdresse komplett angeben, bei 
2 dagegen der Offset der zum aktuellen PC hinzuaddiert werden muß.
Variante 1 benötigt den längeren Befehlscode da die absolute adresse 
eben 16 bit o.ä lang ist, während die relative Addresse mit weniger bits 
(bspw 8) auskommt. deshalb führt die verwendung von relativen Sprüngen 
zu kürzeren und schnelleren Code.

Welche Sprungarten es nun gibt ist von CPU zu CPU unterschiedlich. Die 
älteren Semester erinnern sich sicher noch an x86 mit den 
Segmentregister, da müsste gut zwischen short jumps, und far jumps 
unterscheiden.

http://x86.renejeschke.de/html/file_module_x86_id_147.html

Bei absoluten Sprungzielen kann man das Ziel einfach mit einem Label 
markieren und der assembler ersetzt es mit der ermittelden 
Speicheraddressen.

Bei relativen Sprüngen kommt es auf dem assembler an. bei manchen kann 
man in dem Memnomics mit absoluten Label arbeiten und der assembler 
rechnet das in den passenden relativen Sprung um.
Oder man gibt anhand der Anzahl und länge der zu überspringenden 
Addressen selbst den Offset. Da hilft eine reference card , ein A4 
Ausdruck mit einer Tabelle die die länge der einzelnen Befehle 
auflistet. Hat man früher auf karrierten Papier selbst geschrieben. Oft 
braucht man eine solche Tabelle garnicht da die Befehle bis aug 
einzelnen Ausnahmen (Sprünge mit absoluter adresse) gleich lang sind:
https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set#Instruction_list

Als 3 Möglichkeit die relative addresse zu bestimmen schaut man in das 
von assembler erzeugte adress listing, da steht nämlich zu jeden Befehl 
die Speicheraddresse, der rest ist kopfrechnen:
http://www.avrfreaks.net/forum/how-do-you-view-assembly-listing-after-compile

Richtig spannend sind die Möglichkeiten der PC-referenzierung bei 32bit 
RISC maschinen wie ARM.
Da kann man nicht nur munter auf dem PC addieren sondern auch 
Unterprogrammrücksprungaddressen selbst verwalten (mv PC , r14).
Und alle Instructionen sind gleich lang (32bit).

Dort wird man aber eher selten den assemblercode selber schreiben, da 
genügt lesen können und das verständnis das PC = pc+2 nicht das selbe 
ist wie BRANCH ghjklabel.

http://www.toves.org/books/armsub/
http://www.peter-cockerell.net/aalp/html/ch-2.html

MfG,

PS:
Die Ausführungen unter dem Pseudonym MaWin gehen am Kern der Frage 
vorbei, deine Frage ist keinesfalls bullshit.

von Fpgakuechle K. (Gast)


Lesenswert?

Georg schrieb:
> Felix schrieb:
>> ist das Sprungziel statt einem Label/Sprungmarke einfach der aktuelle
>> stand des Programmcounters+2
>
> Das ist auch keineswegs ein anderer Befehl, JMP PC+Dist ist genau das
> Gleiche wie JMP Label, nur rechnet beim Label der Assembler den Abstand
> selbst aus, und zwar immer richtig, sofern der Sprung überhaupt möglich
> ist. Man kann also nicht das geringste einsparen und verzichtet nur
> völlig unnötig auf Bedienkomfort,

Stimmt so pauschal nicht, relative sprünge sind in der regel kürzer (1 
instructionword) als Sprünge zu absoluten sprungzielen (2 instruction 
words)

http://www.atmel.com/images/Atmel-0856-AVR-Instruction-Set-Manual.pdf

S. 28 BREQ -> 16 bit Instruction
S. 79 JUMP -> 32 bit Instruction

Relative und absolute Sprünge sind zwei unterschiedliche Befehle.

MfG,

von Georg (Gast)


Lesenswert?

Fpga Kuechle schrieb:
> relative sprünge sind in der regel kürzer (1
> instructionword) als Sprünge zu absoluten sprungzielen (2 instruction
> words)

Ach, das ist mir jetzt völlig neu. Das Thema war: der TO hat eine 
alternative Schreibweise für Sprungziele entdeckt. Dass es sich dabei 
eben nur um eine Schreibweise handelt und sich am erzeugten Sprungbefehl 
garnichts ändert, wie ich geschrieben habe, ist also keineswegs der 
totale Blödsinn als das du das jetzt darstellst.

Aber so eine Falschinterpretation ermöglicht es dir, einen total 
überflüssigen Monsterpost dazu zu plazieren, der nur deinem Ego dient. 
Glückwunsch. Vielleicht belehrst du uns noch über ein paar andere 
Selbstverständlichkeiten, nach denen niemand gefragt hat?

Georg

von Ulrich F. (Gast)


Lesenswert?

Georg schrieb:
> Vielleicht belehrst du uns noch über ein paar andere
> Selbstverständlichkeiten, nach denen niemand gefragt hat?

Gerne:
Aus meinem Blickwinkel erhöht die Verwendung von Sprungzielbezeichnern 
die Lesbarkeit und damit die Wartbarkeit des Programms.
Wenn jemand alleine im stillen Kämmerlein arbeitet, dann von mir aus, 
ohne Labels. Im Team, oder wenn man den Code irgendwo publizieren 
möchte, ist das schon (fast) eine Gemeinheit.

von Fpgakuechle K. (Gast)


Lesenswert?

Georg schrieb:
> Fpga Kuechle schrieb:
>> relative sprünge sind in der regel kürzer (1
>> instructionword) als Sprünge zu absoluten sprungzielen (2 instruction
>> words)
>
> Ach, das ist mir jetzt völlig neu. Das Thema war: der TO hat eine
> alternative Schreibweise für Sprungziele entdeckt. Dass es sich dabei
> eben nur um eine Schreibweise handelt und sich am erzeugten Sprungbefehl
> garnichts ändert, wie ich geschrieben habe, ist also keineswegs der
> totale Blödsinn als das du das jetzt darstellst.

Nein das ist keine alternative Befehl-Schreibweise, das ist ein anderer 
Befehl. Schau den erzeugten ICode an.

Es ist auch keine alternative Schreibweise für Sprungziele es ist 
kürzeres Sprungziel (8 bit) statt 16bit. Eben wie "8 und 16 bit" 
befehler, "char und int".

Siehe auch 
http://stackoverflow.com/questions/4697877/relative-vs-absolute-jmp-in-assembly

> Aber so eine Falschinterpretation ermöglicht es dir, einen total
> überflüssigen Monsterpost dazu zu plazieren, der nur deinem Ego dient.

Bleib mal locker, wenn Dich Computerarchitektur und mikrocontroller 
nicht interessiert dann ist das dein Problem - nicht meins.

MfG,

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Fpga Kuechle schrieb:
> PS:
> Die Ausführungen unter dem Pseudonym MaWin gehen am Kern der Frage
> vorbei, deine Frage ist keinesfalls bullshit.

 Nein, deine total überflussigen und überlangen "Erklärungen" gehen am
 Kern der Frage vorbei, da TOs Frage mit Sicherheit bullshit ist.
 Warum sollte jemand bei klarem Verstand die Sprungbefehle so
 schreiben ?

Fpga Kuechle schrieb:
> S. 28 BREQ -> 16 bit Instruction
> S. 79 JUMP -> 32 bit Instruction
>
> Relative und absolute Sprünge sind zwei unterschiedliche Befehle.

 Erstens:
 BREQ ist ein bedingter Sprung, geht nur bis -63/+64 und ist somit
 immer relativ.

 Zweitens:
 JMP für sich alleine ist auch kein absoluter Sprung, kann aber den
 gesammten FLASH abdecken.
 RJMP für sich alleine ist kein relativer Sprung, da er aber nicht
 den gesammten FLASH erreichen kann, sondern nur +/- 4KB, wird er
 relativ genannt.
 In beiden Fällen wird die angegebene Sprungmarke vom Assembler in
 eine Adresse umgerechnet und steht im HEX-File als absolute
 Adresse für JMP, als Offset für RJMP.
 Also, erst mal informieren und dann schreiben.

 Was du hier erfolglos mit vielen Wörtern und wenig Sinn zu erklären
 versuchst, ist wahrscheinlich relokativer code und das ist bei
 kleinen AVRs immer der Fall, also uninteressant in diesem Zusammenhang.

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Fpga Kuechle schrieb:
>> Das ist auch keineswegs ein anderer Befehl, JMP PC+Dist ist genau das
>> Gleiche wie JMP Label, nur rechnet beim Label der Assembler den Abstand
>> selbst aus, und zwar immer richtig, sofern der Sprung überhaupt möglich
>> ist. Man kann also nicht das geringste einsparen und verzichtet nur
>> völlig unnötig auf Bedienkomfort,
>
> Stimmt so pauschal nicht, relative sprünge sind in der regel kürzer (1
> instructionword) als Sprünge zu absoluten sprungzielen (2 instruction
> words)

Ich glaube, die ganze Diskussion um absolute und relative Sprünge beruht
auf einem Missverständnis:

Der Name "PC" im AVR-Assembler von Atmel steht nicht etwa für das
Programm-Counter-Register des Prozessors, sondern für den Adresszähler
des Assemblers der während des Assemblierens hochgezählt wird. Das ist
eine Softwarevariable auf dem Entwicklungsrechner und hat mit der
AVR-Hardware nicht das Geringste zu tun.

Deswegen liefern
1
  JMP PC+Dist

und
1
  JMP Label

bei gleichem Sprungziel tatsächlich den gleichen 32-Bit-Opcode mit
absoluter Adressierung. Die Verwendung von "PC" Operanden ändert im
generierten Code nicht die absolute in relative Adressierung, und die
Addition von PC und Dist erfolgt nicht auf dem Ziel- sondern auf dem
Entwicklungsrechner.

Will man einen relativen Sprung, muss man den RJMP-Befehl verwenden.

Beim Gnu-Assembler heißt das entsprechende Symbol nicht "PC", sondern
".", was meiner Meinung nach weniger missverständlich ist.

von Fpgakuechle K. (Gast)


Lesenswert?

Marc Vesely schrieb:
> Fpga Kuechle schrieb:
>> PS:
>> Die Ausführungen unter dem Pseudonym MaWin gehen am Kern der Frage
>> vorbei, deine Frage ist keinesfalls bullshit.
>
>  Nein, deine total überflussigen und überlangen "Erklärungen" gehen am
>  Kern der Frage vorbei, da TOs Frage mit Sicherheit bullshit ist.
>  Warum sollte jemand bei klarem Verstand die Sprungbefehle so
>  schreiben ?

Weil sie ebenso geschrieben werden (können) (lt. mnemonic datenblatt) 
oder C-Compiler eben Assemblercode erzeugen der so ausschaut, Bspw aus 
Raspi.


>  BREQ ist ein bedingter Sprung, geht nur bis -63/+64 und ist somit
>  immer relativ.

>  JMP für sich alleine ist auch kein absoluter Sprung, kann aber den
>  gesammten FLASH abdecken.

>  RJMP für sich alleine ist kein relativer Sprung, da er aber *nicht*
>  den gesammten FLASH erreichen kann, sondern nur +/- 4KB, wird er
>  relativ genannt.

?alleine, nicht alleine? absolut| nicht absolut? Bedingt, nicht bedingt?

Der TO fragt hier nach unterschiedlichen Sprung-"zielen", nicht nach 
bedingten oder unbedingten Sprung-"modi". Also stellt sich nur die Frage 
nach relativer (PC <- PC+x) und absoluter (PC <- K)  Adressierung. Und 
da sollte man nicht behaupten das "springe label" das selbe wäre wie 
"Springe relativ". Spätestens wenn das Label auf eine Adresse verweist 
die ausserhalb der Sprungweite der relativen addressierung wird das dem 
TO böse auf die Füße fallen.

>  In beiden Fällen wird die angegebene Sprungmarke vom Assembler in
>  eine Adresse umgerechnet und steht im HEX-File als *absolute*
>  Adresse für JMP, als Offset für RJMP.
>  Also, erst mal informieren und dann schreiben.

Link auf datenblatt übersehen?

>
>  Was du hier erfolglos mit vielen Wörtern und wenig Sinn zu erklären
>  versuchst, ist wahrscheinlich relokativer code und das ist bei
>  kleinen AVRs immer der Fall, also uninteressant in diesem Zusammenhang.

Das ist ein Aspekt der relativen Adressierung, aber nicht der einzige.
Der Kern der Frage ist der Unterschied zwischen relativer Addressierung
des Sprungziels und absoluter.

Und aus dem subject dieses therads kann ich keine Einschränkung auf 
kleine AVR herauslesen, nicht mal Einschränkung auf AVR, denn da steht 
"Assembler Programmcounter". Deshalb ist es auch Falsch die Frage als 
"bullshit" abzutun weil man aus dem individuellen Erkenntnishorizont 
"kleine AVR" keine Anwendung parat hat.

Und das es sich bei dem vom TO gezeigten Codeschnipsel explizit um 
lageunabhängigen Code handelt kann ich auch nicht erkennen. Ob der 
erwähnte
Atmega324 ein "kleiner AVR" ist, ist ebenfalls strittig aber mindestens 
Geschmackssache.

MfG,

von Fpgakuechle K. (Gast)


Lesenswert?

Yalu X. schrieb:

>
> Ich glaube, die ganze Diskussion um absolute und relative Sprünge beruht
> auf einem Missverständnis:

Damit hast du IMHO nicht ganz unrecht.

> Beim Gnu-Assembler heißt das entsprechende Symbol nicht "PC", sondern
> ".", was meiner Meinung nach weniger missverständlich ist.

Interessante neue Info, beim ARM-Assembler bedeudet dagegen PC 
tätsächlich den programm counter des Cores.

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0473c/CJAJBFHC.html

Und bei (den meisten) ARM-Cores ist der PC genauso breit wie ein 
Instructionword und die GP-Regs.

MfG,

von (prx) A. K. (prx)


Lesenswert?

Fpga Kuechle schrieb:
> Macht der ARM Cortex M4 ebenfalls:

> Durch die bedingte
> Ausführung der meisten  ARM Befehle werden so bedingte Sprünge "im
> vorbeigehen" implementiert.

Das trifft auf den klassischen ARM Befehlssatz zu, nicht aber auf dem 
Thumb2 Befehlssatz der Cortex M4.

von (prx) A. K. (prx)


Lesenswert?

Netterweise unterscheiden sich Atmels und GNUs Assembler nicht nur in 
der Syntax bei der Angabe der Befehlsadresse (PC v. "."): Atmel rechnet 
im Programadressraum in Worten, GNU aber in Bytes, weshalb die 
Distanzangabe in der GNU Variante doppelt so gross ist.

von Yalu X. (yalu) (Moderator)


Lesenswert?

A. K. schrieb:
> Netterweise unterscheiden sich Atmels und GNUs Assembler nicht nur in
> der Syntax bei der Angabe der Befehlsadresse (PC v. "."): Atmel rechnet
> im Programadressraum in Worten, GNU aber in Bytes

Kann es sein, dass auch der Offset verschieden ist?

Beim GNU-Assembler zeigt "." auf den Anfang des jeweils nächsten
Befehls, beim Atmel-Assembler scheint PC auf den Anfang des aktuellen
Befehls zu zeigen (s. Eröffnungsbeitrag).

Ein JMP . bzw. JMP PC hätte also bei GNU außer dem Verbrauch von
Taktzyklen überhaupt keinen Effekt, würde aber bei Atmel eine leere
Endlosschleife erzeugen.

Aber genau um solchen Problemen aus dem Weg zu gehen, benutzt man, wenn
möglich, Labels. Der Assembler will ja auch ein Bisschen was zu tun
bekommen.

: Bearbeitet durch Moderator
von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Yalu X. schrieb:
> Beim Gnu-Assembler heißt das entsprechende Symbol nicht "PC", sondern
> ".", was meiner Meinung nach weniger missverständlich ist.

 "$" ist auch weniger missverständlich.

Yalu X. schrieb:
> Der Name "PC" im AVR-Assembler von Atmel steht nicht etwa für das
> Programm-Counter-Register des Prozessors, sondern für den Adresszähler
> des Assemblers der während des Assemblierens hochgezählt wird. Das ist
> eine Softwarevariable auf dem Entwicklungsrechner und hat mit der
> AVR-Hardware nicht das Geringste zu tun.

 Eigentlich schon, nur ist eben PC (Programm-Counter) in diesem
 Zusammenhang relativ ;-)
 PC+4 ist immer Programm Counter + 4, nur hat der PC nicht denselben
 Wert wenn mit .org 0x100 oder mit .org 0x200 assembliert wird.

Yalu X. schrieb:
> Kann es sein, dass auch der Offset verschieden ist?
>
> Beim GNU-Assembler zeigt "." auf den Anfang des jeweils nächsten
> Befehls, beim Atmel-Assembler scheint PC auf den Anfang des aktuellen
> Befehls zu zeigen (s. Eröffnungsbeitrag).

 Beim Atmel zeigt PC tatsachlich auf den Anfang des aktuellen Befehls.
 Ob das unlogisch ist, bleibt diskutabel, für mich ist es jedenfalls
 nicht, weil sich dieser RJMP auf aktuelles Befehl bezieht und der
 beginnt eben in dieser Zeile.

von (prx) A. K. (prx)


Lesenswert?

Yalu X. schrieb:
> Beim GNU-Assembler zeigt "." auf den Anfang des jeweils nächsten
> Befehls,

Sicher? https://sourceware.org/binutils/docs/as/Dot.html#Dot

von Fpgakuechle K. (Gast)


Lesenswert?

A. K. schrieb:
> Fpga Kuechle schrieb:
>> Macht der ARM Cortex M4 ebenfalls:
>
>> Durch die bedingte
>> Ausführung der meisten  ARM Befehle werden so bedingte Sprünge "im
>> vorbeigehen" implementiert.
>
> Das trifft auf den klassischen ARM Befehlssatz zu, nicht aber auf dem
> Thumb2 Befehlssatz der Cortex M4.

Ebenso thumb2 der anderen Cortex etc, ebenso der Vorläufer "thumb".
https://en.wikipedia.org/wiki/ARM_architecture#Thumb

Wobei thumb ja eher ein "Betriebsmodus"/Feature ist in dem man die ARM's 
die thumb unterstützen betreiben kann, aber nicht muß.

MfG,

von Yalu X. (yalu) (Moderator)


Lesenswert?

A. K. schrieb:
> Sicher? https://sourceware.org/binutils/docs/as/Dot.html#Dot

Das scheint für Daten und Programmcode unterschiedlich zu sein:
1
  cli
2
loop:
3
  rjmp .+0
4
next:
5
  rjmp .-4
6
7
data: .word .

ergibt
1
Disassembly of section .text:
2
3
00000000 <__ctors_end>:
4
   0:   f8 94           cli
5
6
00000002 <loop>:
7
   2:   00 c0           rjmp    .+0             ; 0x4 <next>
8
9
00000004 <next>:
10
   4:   fe cf           rjmp    .-4             ; 0x2 <loop>
11
12
00000006 <data>:
13
   6:   06 00           .word   0x0006  ; ????

von (prx) A. K. (prx)


Lesenswert?

Fpga Kuechle schrieb:
> Wobei thumb ja eher ein "Betriebsmodus"/Feature ist in dem man die ARM's
> die thumb unterstützen betreiben kann, aber nicht muß.

Die Cortex M Serie kennt nur den Thumb bzw. Thumb2 Modus. Die 
klassischen ARM Befehle existieren bei diesen Cores überhaupt nicht. Der 
im Wikiedia-Artikel erwähnte alte ARM7TDMI ist hingegen ein klassischer 
ARM7 mit zusätzlicher Thumb-Option, wie in den LPC2000.

Vorsicht Falle: ARM7 ist ein Core, ARMv7 eine Befehlssatz-Architektur, 
die Nummern haben keinen Bezug zueinander: ARM7TDMI=ARMv4T, CM0=ARMv6-M, 
CM3=ARMv7-M.

Bedingte Ausführung allgemeiner Befehle gibt es in Thumb überhaupt 
nicht, in Thumb2 per Präfix-Befehl. Die bedingten Sprünge sind aber in 
Thumb und Thumb2 eben gerade nicht unbedingte Befehle mit IT-Präfix, 
sondern ganz klassisch wie in anderen Architekturen auch.

: Bearbeitet durch User
von Fpgakuechle K. (Gast)


Lesenswert?

A. K. schrieb:
> Fpga Kuechle schrieb:
>> Wobei thumb ja eher ein "Betriebsmodus"/Feature ist in dem man die ARM's
>> die thumb unterstützen betreiben kann, aber nicht muß.
>
> Die Cortex M Serie kennt nur den Thumb bzw. Thumb2 Modus. Die
> klassischen ARM Befehle existieren bei diesen Cores überhaupt nicht. Der
> im Wikiedia-Artikel erwähnte alte ARM7TDMI ist hingegen ein klassischer
> ARM7 mit zusätzlicher Thumb-Option, wie in den LPC2000.

Unglaublich aber wahr. Hab gearde im M3/M4 Standardwerk 
978-0-12-408082-9
nachgelesen diese beiden sind immer im T-Mode. Danke für die 
Klarstellung.

MfG,

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.