Forum: Compiler & IDEs avr-as und avr-ld


von AndreasH (Gast)


Lesenswert?

Hallo,

ich habe ein Programm umgeschrieben von einem anderen assembler auf den
avr-gcc bzw. avr-as. Die Dateien bekomme ich einwandrei compiliert. Nur
mit dem Linken klappt es nicht so.
Compiliert habe ich mit diesem Befehl:
"avr-gcc -c -mmcu=at90s2313 -I. -x assembler-with-cpp
-Wa,-adhlns=kernel.lst,-gstabs  Datei1.S -o Datei1.o"

Nur mit dem Linken klappt es nicht.
Wenn ich alle Dateien mit dem avr-gcc linken will muss immer eine
C-Datei dabei sein.
Der Befehl sieht dann folgendermassen aus:
"avr-gcc -mmcu=at90s2313 -I. -g -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall
-Wstrict-prototypes -Wa,-adhlns=main.o  -std=gnu99 main.o   datei1.o
datei2.o datei3.o   --output main.elf -Wl,-Map=main.map,--cref -lm"
Das Programm läuft dann auch solange bis der erste interrupt kommt.
In den Assembler-Dateien sind feste org-Anweisungen. Dies darf aber
wohl nicht sein wenn eine main.c dabei ist.

Wie muss der Linkeraufruf aussehen wenn ich nur die Assembler-Dateien
linken will?

Danke
Andreas

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> In den Assembler-Dateien sind feste org-Anweisungen. Dies darf aber
> wohl nicht sein wenn eine main.c dabei ist.

.org kannst du für jegliche Toolchain vergessen, die verschieblichen
Objektcode mit anschließendem Linken benutzt.  D.h., es war eigentlich
schon vor 20 Jahren unter CP/M ,,out''.  Sogar das CP/M selbst wurde
aus verschieblichen Objektmoduln gelinkt und hat statt .org .phase
benutzt.

Ja, ich weiß, dass der Linker durchaus auch mit .org zurecht kommt,
aber vergiss es dennoch, es hat keinen Sinn.  Wenn du irgendwas auf
eine bestimmte Adresse haben willst, dann sag das dem Linker, nicht
dem Assembler (z.B. indem man dafür eine eigene section aufmacht und
mit --section-start arbeitet).

> Wie muss der Linkeraufruf aussehen wenn ich nur die
> Assembler-Dateien linken will?

Typischerweise linkt man, wenn man das C-Laufzeitsystem dabei haben
will (also vor allem die Startup-Routinen, Interruptvektoren etc.)
über einen Aufruf von avr-gcc, weil der sich um den Rest kümmert.
Wenn du in die Kommandozeile ein -v mit aufnimmst, siehst du, was der
Compiler dem Linker alles mit auf die Reise gibt.

Wenn du ausschließlich Assemblerdateien hast und auch Dinge wie die
Interruptvektoren komplett selbst schreiben willst, dann kannst du den
Linker ,,zu Fuß'' aufrufen.  Sehr wahrscheinlich musst du dann auch
deinen eigenen Linkerscript zimmern oder du hälst dich an die
Konventionen, die das C-Laufzeitsystem benutzt und nimmst dessen
Linkerscript -- aber dann stellt sich die Frage, warum du's überhaupt
noch zu Fuß machen willst.

Falls du was Konkretes im Auge hast, solltest du natürlich auch
konkret werden.  ,,Es geht nicht'' ist keine sinnvolle Beschreibung.

von AndreasH (Gast)


Lesenswert?

Hallo Jörg,

danke für die Antwort.
Mein "es geht nicht" war darauf bezogen, dass das Programm anläuft
dann aber beim ersten Interrupt hängenbleibt.
Zwischenzeitlich bin ich einen Schritt weiter. Ich muss nur die C-Datei
weglassen und in die Assembler-Datei ein label main: einfügen.
Dann geht es soweit.
Der Grund warum ich das mit dem avr-gcc statt avr-as machen will ist,
dass es erhebliche #defines in den Header-Dateien des
Assembler-Programms gibt. Das würde mir einiges an Arbeit sparen.

Mit den interrupt-adressen werde ich noch weitersehen. Das stört mich
im Moment noch nicht. Weiss aber ungefähr wie Du das meinst.

Jetzt habe ich aber ein neues Problem.
Meine Variablen deklariere ich folgendermassen:
            .comm X,1
            .comm Y,1
            .comm Z,1
Jetzt hätte ich gerne, dass der Linker mir die alle hintereinander
setzt. Sie werden aber irgendwo hin gepackt. z.B. erhält X die Adresse
0x88, Y = 0x8C und Z= 0x80.
Ich benötige die aber unbedingt hintereinander.
Die drei Variablen waren jetzt nur ein Beispiel mit denen ich es aber
tatsächlich nochmal ausprobiert habe weil ich mir nicht sicher war.
Wie sag ich es dem Linker?

KAnn ich mir irgendwie eine Liste ausdrucken lassen mit den Adressen
der einzelnen Variablen. Im moment rufe ich immer AVR-Studio auf. Das
ist mir zu umständlich.

Danke
Andreas

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Zwischenzeitlich bin ich einen Schritt weiter. Ich muss nur die
> C-Datei weglassen und in die Assembler-Datei ein label main:
> einfügen.

Ja, das ist das, was die C-runtime aufruft.

(Variablenanordnung)

> Jetzt hätte ich gerne, dass der Linker mir die alle hintereinander
> setzt.

Nö, die Reihenfolge ist komplett dem Linker überlassen.  Du musst eine
große Variable anlegen und darin mit Offsets arbeiten (das ist
letztlich das, was der Compiler bei einer struct macht).

> Wie sag ich es dem Linker?

Wenn du das partout so haben willst, dann nur über einen custom linker
script und eine section für jede Variable.  Ist 'ne ziemliche Kanone
für so einen Spatzen...

> KAnn ich mir irgendwie eine Liste ausdrucken lassen mit den Adressen
> der einzelnen Variablen.

Klar, das nennt sich Symboltabelle und wird von avr-nm generiert.

> Im moment rufe ich immer AVR-Studio auf. Das ist mir zu umständlich.

Das verstehe ich. ;-)  Wo kann man sich denn dort die Symboltabelle
angucken?  Ich habe das neulich gesucht (weil ich nur eine UBROF-Datei
vom IAR hatte, die man sonst mit nichts bearbeiten kann) und nix
gefunden außer dem kompletten Disassemblerlisting, in dem man weder
suchen kann noch kann man es in direkt in eine Datei abspeichern.
cut&paste geht zwar, ist aber schweinig lahmarschig beim Image eines
ATmega128, der nur zu 20 % gefüllt ist...

von AndreasH (Gast)


Lesenswert?

Danke für die Antwort.

Das mit dem avr-nm habe ich auch schon gefunden. Das stimmten die
Adressen mit dem Avr-Studio überein.

Nee im Avr-Studio gibt es solch eine Tabelle nicht. Habe ich mal wieder
nicht klar beschrieben weil ich es nicht wichtig fand.
Ich greife direkt am Programmanfang zum Test auf die Variablen mit sts
zu. Nur um die Adresse rauszubekommen.
Ich lese die reine Hex-Datei des avr-gcc in Avr-Studio ein und weiss
dann, wenn der sts-Befehl kommt, dass es sich um die entsprechende
Variable handelt.
Was einfacheres ist mir nicht eingefallen.

von AndreasH (Gast)


Lesenswert?

Ich habe trotzdem nochmal eine Frage.

Bei der Durchsicht der von avr-nm erzeugten Tabelle ist mir
aufgefallen, dass der gcc Variablen in Speicherbereiche anlegt, die der
Controller überhaupt nicht hat.
Hierüber hatte ich mich auch schon beim debuggen mit avr-studio
festgestellt.

Beispiel:
angegeben hatte ich im Makefile: MCU = at90s2313
Folgenden Variablen hatten die entsprechenden Adressen erhalten:
008000e0 B sTxMsgBuf
008000f0 B RxId_1
008000f8 B TxBuf
00800100 B RxBuf_1
00800108 B TxLen
00800109 B RxLen_1
0080010a B TxId


Der Speicherbereich des 2313 geht aber nur bis $DF.

Was habe ich denn hier beim Aufruf falsch gemacht?

Danke schon mal im Voraus

Andreas

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Nichts.  Die 0x800000 sind der Offset, der kennzeichnet, dass diese
Variable im RAM liegt.  Das ist 'ne Krücke, damit der GCC die
Harvard-Architektur (für die er nie konzipiert worden ist) überhaupt
irgendwie schluckt.  Der EEPROM hat Offset 0x810000.

von AndreasH (Gast)


Lesenswert?

Das ist schon klar. Das meinte ich auch anders.

Aber wenn ich z.B. von der "0080010a B TxId" die 800000 abziehe, hat
die immer noch die Adresse 10a. Das geht über den Speicherbereich des
2313 hinaus.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

> Das geht über den Speicherbereich des
> 2313 hinaus.

Das ist natürlich wahr...  War mir nicht aufgefallen, ich habe
lange nichts mehr mit so kleinen AVRs gemacht.

Ich denke, da hast du wohl insgesamt ein Problem.

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.