Hallo Leute,
ich habe ein AVR ASM Projekt. Das will ich jetzt erweitern und zwar mit
C.
Mein Problem ist jetzt, dass ich dem Assembler-code die C Funktionen
bekannt machen muss.
Ich kenne dieses Paper: http://www.atmel.com/images/doc42055.pdf
Wenn ich aber im Code
1
.extern mycfunction
erhalte ich eine Fehlermeldung:
1
Invalid directive: '.extern'
Mein Projekt ist initial ein ASM Projekt und ich will jetz C Code
hinzufügen.
Die generierte Programmzeile ist:
Adib schrieb:> Es scheint, als ob der Assembler die Direktive .extern nicht kennt. ?
Klar, wofür auch?
Das Ding ist doch ein Primitiv-Assembler, der nur als Absolutassembler
arbeiten kann und keinen Linker kennt. Was sollte er dann mit einem
als extern deklarierten Symbol anfangen können?
Beim GNU-Assembler kannst du sowas machen, aber der hat halt rundum
eine andere Syntax als der von Atmel, du müsstest also deinen Quellcode
umschreiben.
Adib schrieb:> Hallo Leute,>> ich habe ein AVR ASM Projekt. Das will ich jetzt erweitern und zwar mit> C.
Falsche Vorgehensweise.
Du willst nicht ein Assembler Projekt mit C erweitern sondern du willst
ein C Projekt neu beginnen, in dem du von C aus an ausgewählten Stellen
Funktionen aufrufst, die in Assembler geschrieben sind.
Damit C Code laufen kann gilt es Vorbedingungen einzuhalten. Da muss
eine Runtime Umgebung aufgesetzt werden, ehe dann dein main() erstmals
die Kontrolle kriegt. Diese Umgebung wird vom Startup-Code eingerichtet,
die du in einem C Projekt immer automatisch mit dabei hast. Startest du
mit einem Assembler Projekt, dann fehlt diese Einrichtung.
Allerdings erhebt sich die Frage, warum du Teile deines Programms in
Assembler schreiben willst. Es gibt natürlich Fälle an denen dies
notwendig ist, weil man 100% taktgenaues Code-Timing benötigt. Ist
dieser Fall nicht gegeben, dann ist es das vernünfigste den Code noch
mal neu in C zu formulieren.
Wenn das nicht geht, dann musst du eben bei Assembler bleiben und deine
Erweiterungen in Assembler machen.
Das ist eben die Krux an Assembler: du bist zu nichts kompatibel und
kannst nur mit viel Aufwand aus diesem Korsett ausbrechen. Ein in
Assembler vorliegendes Programm mal eben so durch neue Funktionalität in
einer anderen Sprache erweitern spielt es da nicht.
Adib schrieb:
Das Problem liegt hier:
> avrasm2.exe
Du brauchst einen Assembler/Linker, der ABI-kompatibel mit dem
GNU-Assembler ist, da avr-gcc diesen als "Backend" verwendet.
Ein Assembler, der ABI-kompatibel zum GNU-Assembler ist, ist natürlich
der GNU-Assembler selbst :-)
Jörg W. schrieb:> Beim GNU-Assembler kannst du sowas machen, aber der hat halt rundum> eine andere Syntax als der von Atmel, du müsstest also deinen Quellcode> umschreiben
Quark. Das von Atmel zitierte Dokument bezieht sich auf den GCC. Und es
funktioniert wie dort beschrieben in beide Richtungen. Wohingegen es in
der Tat ungewöhnlich ist das Assembler C Funktionen aufruft.
Adib schrieb:> Dachte, es wäre einfacher.
Es ist auch ganz einfach! Wenn man weiss wie es geht.
Was Herr Buchegg schreibt bezogen auf das "Framework" ist fast richtig.
Voraussetzung dass es geht, ist dass der GCC Assembler benutzt wird. Um
das ganz einfach zu realisieren setzt man einfach ein GCC "C" Projekt
auf. In das Bindet man ein .s (Assembler-File) ein.
Das man eine "C" main() Funktion benötigt ist quatsch. Ich bin für ein
paar Tage auf Meetings in den USA. Danach kann ich Dir gerne ein AVR
Studio Beispielprojekt senden. Dazu eine PM an mich.
Im Prinzip als Beispiel zum aufrufen einer "C" Funktion aus einem
Assembler Code, schnell getippt, eifach so machen:
C-FILE
1
#include<avr/io.h>
2
3
4
uint8_tmyCFunction(void)
5
{
6
//irgendwas machen wie z.B.
7
volatileuint8_tmyVar=123;
8
return(myVar);
9
}
Und im Assembler File (.s)
1
#include <avr/io.h>
2
#define __SFR_OFFSET 0
3
4
5
6
.extern myCFunction //C-Funktion bekannt machen
7
.global main //main bin jetzt ich da unten
8
9
main: rcall myCFunction //C-Funktion aufrufen
10
nop
11
nop
12
13
rjmp main
14
15
.end
Beachten! Das Label "main" muss auch genau so geschrieben werden
Karl H. schrieb:> Allerdings erhebt sich die Frage, warum du Teile deines Programms in> Assembler schreiben willst. Es gibt natürlich Fälle an denen dies> notwendig ist, weil man 100% taktgenaues Code-Timing benötigt. Ist> dieser Fall nicht gegeben, dann ist es das vernünfigste den Code noch> mal neu in C zu formulieren.
Warum hört ihr eigentlich nicht das ständige Missionieren auf? Besonders
dann wenn jemand eine offensichtlich konkrete Frage hat und nicht
versucht eine Datenbankabfrage in Assembler zu realisieren.
Thomas H. schrieb:>> Beim GNU-Assembler kannst du sowas machen, aber der hat halt rundum>> eine andere Syntax als der von Atmel, du müsstest also deinen Quellcode>> umschreiben>> Quark. Das von Atmel zitierte Dokument bezieht sich auf den GCC. Und es> funktioniert wie dort beschrieben in beide Richtungen. Wohingegen es in> der Tat ungewöhnlich ist das Assembler C Funktionen aufruft.
Ärger mit dem Chef gehabt oder was?
Was Jörg da schrieb, ist kein Quark, sondern exakt dasselbe, was Du dann
nochmal drunter geschrieben hast.
Stefan
Thomas H. schrieb:> Quark. Das von Atmel zitierte Dokument bezieht sich auf den GCC.
Ist „Quark“ dein „von Atmel zitierte(s) Dokument“? Ansonsten sehe
ich da kein solches, aber ein
recht prominent im ersten Beitrag, und das ist nun einmal nicht
der GNU-Assembler, und ein für diesen Atmel-Assembler geschriebener
Quellcode läuft auch nicht 1:1 durch den GNU-Assembler durch.
Behalt' deinen „Quark“ also besser für dich …
Thomas H. schrieb:> Warum hört ihr eigentlich nicht das ständige Missionieren auf?
Wenn man den Assembler-Quelltext ohnehin (mehr oder minder umfassend,
wir haben ihn ja nicht gezeigt bekommen) anfassen muss, dann stellt
sich schon sehr wohl die Frage, ob man ihn nicht mit weniger Aufwand
hernach gleich in C verfassen kann. Wie Karl Heinz schon schrieb,
die Initialisierung des Laufzeitsystems muss man ohnehin C-konform
vornehmen.
>>> Beachten! Das Label "main" muss auch genau so geschrieben werden
und jetzt hätte ich da gerne noch eine Erklärung, was da jetzt
wahnsinnig besser ist, als gleich
1
intmain()
2
{
3
while(1)
4
myCFunction();
5
}
zu schreiben.
Fazit: Klar kann man die Arbeit vom Compiler auch zu Fuss erledigen.
Aber wozu?
Thomas H. schrieb:> Warum hört ihr eigentlich nicht das ständige Missionieren auf? Besonders> dann wenn jemand eine offensichtlich konkrete Frage hat und nicht> versucht eine Datenbankabfrage in Assembler zu realisieren.
Nun. Irgendeinen Grund wird es schon haben, warum er Teile in C
schreiben will. Ich denke nicht, dass es sich bei den zu schreibenden
Dinge um die trivialsten Teile seines Programmes handelt.
Ausserdem missioniere ich nicht.
Was ich nämlich denke, das ist, dass er von irgendwoher ein Assembler
Programm hat, das er gerne erweitern möchte. Und anstatt das in ein C
Korsett zu zwängen mit all seinen Problemen, wie zum Beispiel
einzuhaltender ABI, würde ich dazu raten den Schritt zu machen und nur
die Teile in Assembler zu belassen, die aus Code-Timing Gründen
taktgenau sein müssen. Die Zeit, die er für einen derartigen Umbau auf
Assembler Ebene benötigt (er benutzt ja noch nicht einmal den richtigen
Assembler dafür), die Zeit kann besser investiert werden. Auch im
Hinblick auf zukünftige Wartungen und/oder Erweiterungen. Denn eines ist
klar: Arbeit muss er so und so investieren. Mit ein paar .extern und
einem call ist es im Regelfall nicht getan, so wie du das suggerierst.
Das funktioniert nur, weil dein Programm nichts anderes macht als genau
die Funktion aufzurufen. Oder weisst du, ob sein Programm ein paar ISR
hat, die sich die Freiheit nehmen einige Register nur für ihre eigene
Verwendung zu reservieren und daher nicht pushen/popen? Das möchte ich
dann sehen, was da rauskommt, wenn ein derartiger Interrupt genau dann
zuschlägt wenn gerade der C-Teil an der Arbeit ist. Oder wenn irgendwo
im Programm an einer ganz anderen Stelle ein Register seinen Wert
behalten soll, welches der gcc als clobber-Register einstuft?
Wir wissen nichts über sein Programm und die Fallstricke, die sich darin
verbergen. Aber eines hab ich im Laufe der Jahre gelernt: die Dinge sind
immer komplexer als ursprünglich gedacht.
Der wesentliche Punkt ist der Wechsel der Sichtweise. Er hat nicht mehr
ein Assembler Programm, das mit C Funktionen aufgepeppt wurde, sondern
die Sichtweise muss sein, dass er ein C Programm hat, dass mit Assembler
Funktionalität aufgepeppt wurde. Das dieser Assembler Anteil am Anfang
durchaus 90% betragen kann, ist ja kein Hindernisgrund. Aber wenn es zu
Problemen kommt (und die wird es voraussichtlich), dann ist immer der
Assembler-Teil an das anzupassen, wie der Compiler die Welt sieht. Und
wenn ich schon anpasse, dann steht selbstverständlich die Überlegung im
Raum: warum nicht gleich zumindest diesen Teil in C neu schreiben, denn
dann kümmert sich der Compiler um das ABI.
Guten Tag die Herren,
ich möchte die ganzen Anfeindungen gemeinsam beantworten, da mir ein
eingehen auf einzelne zu mühsam ist und es vermutlich eh keine Einsicht
bringt.
Ich habe weder ärger mit dem Chef, noch sonst etwas. Ich habe keinen
Chef. Ich bin der Chef.
Ich habe in meinem Leben schätzungsweise Millionen von Zeilen
Assemblercode programmiert und das weder zu Hobby oder anderen privaten
Zwecken, sondern in Bereichen der Industrie, wo dies unumgänglich ist.
Es gibt nämlich mannigfache Gründe so etwas zu tun, auch wenn dem einen
oder anderen hier die Einblicke fehlen. Nicht zuletzt ein Grund warum
Atmel diese AppNote überhaupt herausgibt. Was übrigens auch die anderen
Compilerbauer so machen. Die Schnittstellen zwischen Assembler und C
oder gar C++ sind essentiell für einen Compiler.
Der TO hatte eine ganz konkrete Frage, sich sogar die entsprechende
AppNote herausgesucht. Das bedeutet doch unzweifelhaft dass er eben
diese Frage gerne beantwortet hat. Er hat weder nach der Sinnhaftigkeit
dieses Vorgehens gefragt, noch danach ob generell das Mischen der
beiden Sprachen sinnvoll ist.
Diese Frage wurde mit viel Prosa beantwortet, an der Teile korrekt waren
und andere eben nicht. Darauf hatte ich bereits hingewiesen. Kein
Einziger hat die eigentliche Frage beantwortet, so das der TO sein
Problem lösen konnte. Die Frage wurde vielmehr so beantwortet, mit in
die Irre führenden Hinweisen, man müsse z.B. eine main() Funktion in „C“
zwingenderweise implementieren, das der TO am Ende mehr oder weniger
aufgegeben hat.
Dafür gab es Äußerungen wie:
„Klar, wofür auch?“
„Das Ding ist doch ein Primitiv-Assembler“
„aber der hat halt rundum
eine andere Syntax als der von Atmel“
Das sind Aussagen die inhaltlich falsch, degradierend und nicht
zielführend sind und zudem eines Moderators nicht würdig. Der Code lässt
sich leicht portieren und der Assembler -ist im Gegensatz zu der
Aussage- nicht primitiv. Er macht genau das was ein Assembler können
muss.
Ich habe dem TO ein einfaches funktionierendes Beispiel gegeben welches
zweifelsohne Funktioniert, ohne main() Funktion in „C“. Dass
anschließend jemand kommt und dem funktionierenden Beispiel –das seiner
eigenen vorherigen Aussage gar nicht hätte funktionieren können-
unterstellt das es Sinnfrei ist und durch 3 Zeilen „C“ Code ersetzt
werden kann ist wirklich Lachhaft. Ein Beispiel ist in der Regel
Sinnfrei und ließe sich demnach regelhaft auf Null reduzieren.
Dieses Beispiel beantwortet aber in einfacher Weise die gestellte Frage
und das ist der essentielle und einfache Sinn einer Antwort auf eine
konkrete Frage.
Für mich ist an dieser Stelle diese alberne Diskussion Assembler und „C“
beendet. Die Frage ist beantwortet und wenn der TO noch eine Frage zum
Problem hat oder Hilfe benötigt bitte eine PM Schreiben.
Thomas H. schrieb:> Der Code lässt> sich leicht portieren
Das kann man erst beantworten, nachdem man den Code gesehen hat.
Klar benutzen beide die gleichen AVR-Befehle, aber im gesamten
Bereich der Pseudo-Anweisungen unterscheiden sie sich, und auch in
vielen anderen Details (Registerpaare, Wort-Adress-Behandlung,
Behandlung der IO-Port-Namen).
Je nachdem, wie der Code gezimmert ist, kann man also einiges an
Aufwand reinstecken, den auf den anderen Assembler zu portieren.
BTDT.
> und der Assembler -ist im Gegensatz zu der> Aussage- nicht primitiv.
Er ist dahingehend primitiv, dass er keinen verschieblichen Objektcode
generieren kann, den man zusammen mit anderen Objektmodulen linken
könnte. Genau das benötigt man aber, wenn man den Assemblercode
gemeinsam mit C-Code benutzen will in einem Projekt, und genau darum
ging es in der Frage (und genau deshalb kann er auch kein .extern
kennen).
Warum ich das als „primitiv“ bezeichne? Weil bessere Lösungen schon
vor 40 Jahren existiert haben (und die liefen auf viel kleineren
Maschinen) und es nicht verständlich ist, warum Atmel Jahrzehnte später
noch mit sowas aufwarten musste. Ob du das nun „degradierend“
empfindest, ist mir eigentlich egal – es ist meine Meinung, und ich
habe sie dir hiermit auch begründen können.
Thomas H. schrieb:> Der TO hatte eine ganz konkrete Frage, sich sogar die entsprechende> AppNote herausgesucht. Das bedeutet doch unzweifelhaft dass er eben> diese Frage gerne beantwortet hat. Er hat weder nach der Sinnhaftigkeit> dieses Vorgehens gefragt, noch danach ob generell das Mischen der> beiden Sprachen sinnvoll ist.
Ein Hinterfragen sollte doch mal möglich sein.
Beispiel:
Dich fragt jemand, ob er lieber von der Brücke oder sturzbetrunken ins
Meer springen soll. Wie lautet deine zielführende Antwort?
(Ich weiß: Gehört hier nicht her!)
Ralf G. schrieb:> Ein Hinterfragen sollte doch mal möglich sein.> Beispiel:> Dich fragt jemand, ob er lieber von der Brücke oder sturzbetrunken ins> Meer springen soll. Wie lautet deine zielführende Antwort?> (Ich weiß: Gehört hier nicht her!)
Nun jemand der in suizidaler Absicht nach der besten Art des Suizides
fragt hat meiner Meinung auch eine Antwort auf seine Frage verdient. Der
Freitod aufgrund nicht kurativ
behandelbarer Leiden ist schließlich Gegenstand diverser, auch
politischer Diskussionen. Hier sollte jemandem der fest entschlossen ist
seinem Leben ein Ende zu bereiten durchaus der humanste und schmerz- und
leidensfreiste Weg aufgezeigt werden. Das wäre unter den zwei zur
Auswahl gestellten Wegen sicher der Weg mit der vorher stattgefundenen
Äthyltoxischen Sedierung und dem anschließenden Sprung ins kalte Wasser.
Mit viel Glück kommt es dann zu einer Vasovagalen Reaktion mit
konsekutivem Kreislaufstillstand. Das geht schnell und ist mit wenig
leiden verbunden. Wohingegen Sprünge von einer Brücke oft daneben gehen,
weil entweder die Höhe zu gering gewählt wurde, oder der Suizidant noch
vor dem Fall der gesamten Höhe mit anderen Hindernissen Kollidiert.
Nicht selten, werden solche Personen noch lebend und mit teilweise oder
zur Gänze abgetrennten Gliedmaßen aufgefunden und befinden sich in einer
entsprechenden Schmerzsituation.
Man kann solche, z.B. Krebskranken Menschen natürlich auch volllabern
und ihnen sagen das sei alles nicht ganz so schlimm und es vielleicht
doch besser wäre langsam dahin zu siechen, zu verrotten und zu verwesen
am lebendigen Leibe usw.., aber das ist letzten Endes eine
philosophische Frage und genau deshalb ist der Vergleich einer Frage
nach einer etablierten Technologie und der Form eines Suizides selten
dämlich und gehört wie von ihnen festgestellt nicht hierhin. Aber ich
bin immer bemüht anderen etwas beizubringen. Und ich hoffe ich konnte
ihnen vermitteln das die Art und Weise wie eine Selbsttötung ausgeführt
wird durchaus nicht irrelevant ist.
Ein sinnigerer Vergleich wäre gewesen zu Fragen was ich mache, wenn ich
abends auf der Straße von einem Paar, welches auf der Suche nach dem
nahegelegenen Theater ist und bereits die Karten für die
Abendvorstellung in der Hand hat , weil Sie zu Ihrem Hochzeitstag ein
lange ersehntes Theaterstück sehen wollen, nach dem Weg gefragt werde.
Ich könnte Ihnen (A) einfach die Frage beantworten und Ihnen den Weg
beschreiben.
Ich könnte ihnen (B) lang und breit erklären das Sie doch besser was
anders machen, weil ich finde das dieses Theaterstück nicht besonders
gut ist und der Meinung bin das man eh in seiner Freizeit andere Dinge
macht, anstatt ins Theater zu gehen.
Meine klare Antwort ist (A) Denn das ist Zielführend im Sinne der Frage.
Jörg W. schrieb:> Das kann man erst beantworten, nachdem man den Code gesehen hat.>> Klar benutzen beide die gleichen AVR-Befehle, aber im gesamten> Bereich der Pseudo-Anweisungen unterscheiden sie sich, und auch in> vielen anderen Details (Registerpaare, Wort-Adress-Behandlung,> Behandlung der IO-Port-Namen).
Nein das geht auch zu beantworten ohne den den Code gesehen zu haben!
Gefragt wäre hier eine Portierung von einem,ich Zitiere „primitiven
System“ zu einem besseren. Diese Art der Portierung ist per se
einfacher.
Die Portierung von AVR-Assembler Code zu GCC kann mit Copy&Pate und der
einfachen Such und Ersetzen Funktion der Gängigen Code-Editoren
bewerkstelligt werden. Die wesentlichen Dinge die geändert werden müssen
bei den Direktiven zwischen den beiden Assemblern sind folgende:
GCC: Atmel AVR:
hi8 high
lo8 low
.asciz “hello” .db “hello”, 0
.section .data .dseg
.section .text .cseg
<avr/io.h> “m32def.inc”
Ein Beispiel zur Portierung eines kurzen AVR-Assembler Codes
AVR-CODE
1
.include “m32def.inc”
2
.cseg
3
.org 0
4
rjmp main
5
.org 0x2A
6
main: ldi r16, 0xff
7
out DDRB, r16
8
ldi r16, high(RAMEND-0x20)
9
out SPH, r16
10
ldi r16, low(RAMEND-0x20)
11
out SPL, r16
12
sei
13
rcall lcd_init
14
ldi ZH, high(message)
15
ldi ZL, low(message)
16
rcall prtmsg
17
quit: rjmp quit
18
prtmsg: lpm r24, Z+
19
cpi r24, 0
20
breq exit
21
rcall lcd_print_char
22
rjmp prtmsg
23
exit: ret
24
message: .db “hallo”, 0
Das ganze muss also lediglich wie folgt geändert werden damit es GCC
Kompatibel ist:
1
#include <avr/io.h>
2
#define __SFR_OFFSET 0
3
.section .data
4
.org 0x0
5
message: .asciz "hallo"
6
.section .text
7
.global main
8
9
main: ldi r16, 0xff
10
out DDRB, r16
11
ldi r16, hi8(RAMEND-0x20)
12
out SPH, r16
13
ldi r16, lo8(RAMEND-0x20)
14
out SPL, r16
15
sei
16
rcall lcd_init
17
ldi XH, hi8(message)
18
ldi XL, lo8(message)
19
rcall prtmsg
20
quit: rjmp quit
21
prtmsg: ld r24, X+
22
cpi r24, 0
23
breq done
24
rcall lcd_print_char
25
rjmp prtmsg
Das ist mit search&replace in 2 minuten getan und das ist unabhängig
davon ob der Code 20 Zeilen oder 20000 hat, es geht gerade mal darum 6,
oder 7 Dinge zu ändern.
Jörg W. schrieb:> Je nachdem, wie der Code gezimmert ist, kann man also einiges an> Aufwand reinstecken, den auf den anderen Assembler zu portieren.> BTDT
Jetzt ist in der Tat meine Neugierde geweckt! Und ich wäre jetzt
natürlich sehr an einem Beispiel interessiert wie ein Code gezimmert
sein muss, damit eine Portierung von AVR-Assembler zu GCC einiges an
Aufwand kosten würde.
Thomas H. schrieb:> Hier sollte jemandem der fest entschlossen ist> seinem Leben ein Ende zu bereiten durchaus der humanste und schmerz- und> leidensfreiste Weg aufgezeigt werden. Das wäre unter den zwei zur> Auswahl gestellten Wegen sicher der Weg mit der vorher stattgefundenen> Äthyltoxischen Sedierung und dem anschließenden Sprung ins kalte Wasser.
Ist doch richtig! Nur, wenn du den Grund für seinen Freitod nicht
kennst, dann solltest du erstmal nachfragen.
Thomas H. schrieb:> Jetzt ist in der Tat meine Neugierde geweckt! Und ich wäre jetzt> natürlich sehr an einem Beispiel interessiert wie ein Code gezimmert> sein muss, damit eine Portierung von AVR-Assembler zu GCC einiges an> Aufwand kosten würde.
Kann ich dir leider nicht mehr so genau sagen, war meiner Erinnerung
nach mal Code aus einer Atmel-Appnote. Ich war da auch erstmal
rangegangen mit: „Bisschen Suchen&Ersetzen, kann ja nicht so schlimm
sein.“
Zusätzlich kommt ja beim TE noch hinzu, dass er sich dann um die
Aufrufsequenzen (Registerbenutzung, Parameterübergabe) für den aus
C heraus generierten Code kümmern muss. Wenn man nicht vorsätzlich
seinen Assemblercode bereits aufrufkompatibel dazu schreibt, kann das
auch nochmal einiges an Aufwand werden.
Da wir von Adib aber in diesem Thread ohnehin nichts mehr gehört haben,
hat sich die Angelegenheit wohl vorerst erledigt.
Ralf G. schrieb:> Ist doch richtig! Nur, wenn du den Grund für seinen Freitod nicht> kennst, dann solltest du erstmal nachfragen.
Nun dieses Beispiel ist als Vergleich zur Fragesituation des TO -ich
hatte bereits darauf hingewiesen- inadäquat. Deshalb brachte ich das
andere Beispiel ins Gespräch.
Jörg W. schrieb:> Zusätzlich kommt ja beim TE noch hinzu, dass er sich dann um die> Aufrufsequenzen (Registerbenutzung, Parameterübergabe) für den aus C> heraus generierten Code kümmern muss. Wenn man nicht vorsätzlich seinen> Assemblercode bereits aufrufkompatibel dazu schreibt, kann das auch> nochmal einiges an Aufwand werden.>
Dass ist in der Tat richtig. Ich bin (gehe) davon aus das er dies aber
getan hat, offensichtlich war er ja fest entschlossen das so umzusetzen.
Die Konventionen sind in der AppNote die er zitierte ja beschrieben.
Wenn er das nicht getan hat und sein Code ist umfangreich hätte er
tatsächlich einiges zu tun.
Hallo Leute,
ich hatte in der Vergangenheit schon mal ein Assemblerprojekt mit
existierendem C-Code erweitert. Das war aber ein 8051-Keil-A51/C51
Projekt. Ich habe einen Wrapper geschrieben, der die Register
ensprechend des Aufrufsyntax sichert, setzt und wiederherstellt. Das hat
alles wie erwartet funktioniert.
Dass die Atmel Toolchain 2 unterschiedliche Möglichkeiten für Assembler
Code bietet, hatte ich nicht bedacht.
Ihr habt mir aber bei der Entscheidungsfindung, wie jetzt mit dem
Projekt weiter zu verfahren ist, auf alle Fälle geholfen.
Meine Frage zu der möglichen Länge der Labels
Beitrag "GCC AVR ASM max. Anzahl Zeichen pro Label?" bezog sich auch auf diesen
Code. Die Frage war also komplett falsch gestellt. Es war der AVRASM
gemeint. Lokale Labels (also Labels beginnend mit einer Zahl) werfen
auch einen Syntaxerror....
Nochmal vielen Dank für die viele Zeit, die ihr einsetzt für das
Beantworten der Fragen der Anderen.
Adib.
--
Adib schrieb:> Ihr habt mir aber bei der Entscheidungsfindung, wie jetzt mit dem> Projekt weiter zu verfahren ist, auf alle Fälle geholfen.
Dann würden sich sicher alle, die versucht haben zu helfen, gegenseitig
Diskutiert haben oder sich beschimpft haben freuen wenn Du uns sagst wie
es weiter geht. Denn auch Leute die Fragen beantworten lernen.....
Adib schrieb:> Lokale Labels (also Labels beginnend mit einer Zahl) werfen auch einen> Syntaxerror....
Ja, das ist eine Eigenheit der Unix-Assembler, die auf die mal von
AT&T geschaffene Syntax zurückgeht. Der GNU-Assembler (gas) ist zu
dieser Syntax kompatibel, daher haben wir das dann für den AVR-GCC
geerbt.
Thomas H. schrieb:> Dann würden sich sicher alle, die versucht haben zu helfen, gegenseitig> Diskutiert haben oder sich beschimpft haben freuen wenn Du uns sagst wie> es weiter geht. Denn auch Leute die Fragen beantworten lernen.....
Hallo Thomas,
... eigentlich wollte ich das nicht ausufern lassen und als Troll gelten
...
Die Ausgangssituation: Der Programmierer verlässt die Firma und
hinterlässt merere (gewachsene) Assembler-Projekte mit unterschiedlicher
Komplexität. Die Dateien sind zwischen 3000 und 6000 Zeilen lang. Die
Programmstruktur nicht dokumentiert. Jediglich die Codesequenzen sind
kommentiert, wenigstens was. Die anderen 3 Kollegen programmieren
ausschliesslich C (u.U. mit Assembler-Sequenzen).
Nun müssen Änderungen an den ASsemblerprojekten gemacht werden ....
Der Plan war: Jetz: Möglichst wenig ändern und nur die nötigen neuen
Funktionen implementieren. Wenn möglich in C. Später: evtl. Schrittweise
Portieren in C oder neucodieren in C.
Erkenntisse: 1) Das mit dem "jediglich neue Funktionen in C
implementieren" ist erst mal vom Tisch. Es wird in den
Assembler-Quelltext reinprogrammiert.
Es ist selbst bei den 3000 Zeilen nicht richtig zu erkennen, welche
Prämissen der Quelltext setzt. Und ob die neuen Funktionen nicht derart
in das Programm eingreifen, dass andere Funktionen nicht gehen.
2) das schrittweise Refaktorieren sparen wir uns auch lieber und
3) investieren lieber die verbleibende Zeit bis zur nächsten Anpassung
in das Neuschreiben in C mit einer Dokumentation der Programmstruktur.
Besser wären die Voraussetzungen: wenn es nur ein Programmiersystem
gegeben hätte. Assembler, Compiler, Linker (wie beim Keil A51/C51).
Nicht zu vergessen vom System der "persöhnlichen" Projekte; Nur ein
Mitarbeiter bekommt das Projekt zugeordnet. Der Chef interresiert sich
nicht um das Wie bei der Programmierung. Die Welt ist halt nicht perfekt
...
Das soll jetzt auch keine Breitseite gegen Assemblerprogrammierung sein.
Wenn man halt ein Assemblerprogramm und ein C-Programm schreibt,
arbeitet man auf ganz anderen Abstraktionsebenen und die sind am Ende
schwer zusammenzuführen. Ich schreibe ja kein C-Programm mit lauter
globalen Variablen und Funktionsaufrufen (fast) ohne Parameter.
Für mich persöhnlich bedeutet Assembler-Programmierung gegenüber C:
höherer Codieraufwand, schlechtere Wartbarkeit, keine Standard
Unit-Tests, schlechte Wiederverwertbarkeit, Neuprogrammierung für jedes
Target (AVR, ARM, PC). Unter gewissen Umständen nehme ich das in Kauf:
Laufzeitverhalten, Generieren spezieller Befehlssequenzen, Codegröße.
Soweit von meiner Seite,
schönes WE,
Adib.
--
Hallo Adib,
Vielen dank für die Mühe und das abschließende Aufklären über das
eigentliche Problem. Das ist in der Tat multifaktoriell komplex und da
der Assemblercode nicht von Beginn an in der Absicht der der
"Mischbarkeit" erstellt wurde und zudem nicht durchgehend kommentiert
ist wird es auch keine nichtkomplexe Lösung geben können. Euer Vorgehen
ist deshalb sicher sinnvoll. Einzelkommentare zu "C" oder Assembler zu
deinen aufgezählten Punkten möchte ich hier öffentlich nicht geben, das
gibt nur Sinnlose Diskussionen. Ich komme aus einem Bereich wo aus
diversen Gründen sehr viel alternativlos in Assembler gemacht werden
muss. Ich würde aber auch in anderen Bereichen keinen Programmierer für
Embeded Systeme einstellen der nicht auch perfekt Assembler für die
eingesetzten Typen beherrscht.
Ebenfalls ein schönes WE