Frage zu Gnu Assembler

Gast #6727197
Hallo.

Da ich jetzt vermehrt versuche, strukturiert mit Libs zu arbeiten und 
deshalb auch Libs erstelle, habe ich das Problem, dass ich bei einem 
#include "lib.S" die komplette Lib mitnehme, auch wenn ich daraus nur 
einzelne Funktionen brauche.

Gibt es irgendwie einen Trick, mit dem ich mit Conditionals Blöcke 
hinzufügen kann? Nach dem Motto

.ifcalled some_function
some_function:
code
.endif

C macht das ja bereits so. Wäre halt schön, wenn man das dem Assembler 
auch beibringen könnte.
Moderator Persönliche Seite
Jan schrieb:
> #include "lib.S" die komplette Lib

Das ist keine "Lib" dann.

Eine Library ist eine Sammlung von Objektmoduln, die man dem Linker mit 
auf die Reise gibt, auf dass er aus ihr undefinierte globale 
Symbolreferenzen auflösen kann. Das macht er, indem er jeweils einen 
Modul (also ein .o file) rausnimmt und danach schaut, ob er aus der 
gleichen Library weitere (ggf. auch durch den aktuellen Modul neu hinzu 
gekommene) Referenzen befriedigen kann. Wenn das nichts mehr bringt, 
geht er zur nächsten Library.

Ob die Objektmodule nun aus Assemblerdateien oder aus C-Quellen oder aus 
FORTRAN-Quellen kamen, ist dem Linker egal.

Ergo: alles, was sowieso immer gemeinsam gebraucht wird, kann in eine 
Quelldatei gehen und damit in einen Objektmodul übersetzt werden. 
(Klassiker: malloc und free) Alles, was voneinander logisch unabhängig 
ist, gehört in verschiedene Quelldateien und wird zu verschiedenen 
Objektmodulen übersetzt.

Alle diese Objektmodule werden dann mit dem Librarian zu einer 
Bibliothek verknotet (Dateiendung .a). Die übliche Konvention ist, diese 
lib<irgendwas>.a zu benennen, damit kann man dem Linker dann die Option 
-l<irgendwas> mitgeben, und er sucht sie unter diesem genannten Namen. 
Aber man kann auch lib<irgendwas>.a an der gleichen Stelle der 
Linker-Kommandozeile angeben, das bleibt sich gleich.

Natürlich hat es keinen Sinn, dem Linker ausschließlich Bibliotheken mit 
auf die Reise zu geben. Er hat ja initial kein einziges undefiniertes 
globales Symbol, folglich muss er aus keiner einzigen Bibliothek 
irgendwas entnehmen – und ist gleich wieder fertig mit der Arbeit. Man 
kann sich mit der Linkeroption -u behelfen, um zwangsweise ein 
undefiniertes Symbol von Anfang an zu erzwingen, aber sinnvoller ist es 
natürlich, irgendwas auf der Kommandozeile vor den Libraries zu haben, 
was dann tatsächlich Dinge aus der Lib benötigt, die sich der Linker 
reinziehen muss.
Gast
Danke Jörg. Ich habe offensichtlich nicht verstanden, wie man das mit 
den Libs richtig macht. Gibt es dazu irgendwo ein gutes Tutorial, ohne 
dass man zig Stunden investieren muss, um die gcc internals zu 
verstehen?
Gast
Da ich gerade noch andere Möglichkeiten untersuche.... gibt es eine 
einfache Lösung für folgendes Problem?
1
.ifdef require_some_code
2
some_code:
3
...
4
.endif
5

6
....
7

8
.ifdef require_some_other_code
9
require_some_code = 1
10
some_other_code:
11
...
12
call some_code
13
.endif

ERROR: undefined reference to some_code

Er müsste also weiter oben merken, dass der Code weiter unten benötigt 
wird. Anders gesagt müsste es eine Möglichkeit geben, irgendwas zu 
definieren, was  global gültig wäre. Da es 1001 Möglichkeiten gibt, was 
zu definieren, wollte ich mal fragen, ob da jemand was kennt.
eine Möglichkeit wäre natürlich einzelne Funktionen so zu schreiben, 
dass diese als getennte Dateien übsetzt werden können. Dazu musst du 
dich dann mit public und extern auseinandersetzen.
Beim linken gibst du dann einfach die .o Dateien mit die du brauchst.

Das hat auch nix mit GNU, GCC oder linux zu tun, so arbeitet eigendlich 
jeder Assembler oder Compiler. Ok die ganz primitiven Teile mal ausen 
vor.

Das ist im Prinzip die Vorstufe zu richtigen libs wie es Jörg ja schon 
ausführlich beschrieben hat.
Das ist zu Anfang zwar etwas mer Aufwand bis du den Dreh raus hast. 
Danach wird dir aber vieles in verrschieden toolchains klarer.

Als Literatur könnte ich dir z.B die alten Handbücher zum alten Borland 
Turbo Assembler empfehlen, die sind wirklich gut gemacht. Must halt die 
Sachen mit der Segmentierung ignorieren. Die Handbücher sollten sich in 
einer Archiv Bibliotek finden lassen.
Moderator Persönliche Seite
#ifdef oder .ifdef sind für Bibliotheken eher kontraproduktiv. Sie 
wirken zur Übersetzungszeit, aber die Idee einer Bibliothek ist es ja 
gerade, dass sie nicht jedesmal neu übersetzt wird (egal ob compiliert 
oder assembliert), sondern dass sie vorab übersetzte Objektmodule 
beinhaltet, die bei Bedarf mit dazu gelinkt werden.
Gast
Jörg W. schrieb:
> aber die Idee einer Bibliothek ist es ja
> gerade, dass sie nicht jedesmal neu übersetzt wird

Wie soll das denn gehen? In den Libs verwende ich Befehle wie cbi und 
sbi, die via Konstanten auf die richtigen Ports/Pins zugreifen. Da bei 
jedem Projekt dort andere Zahlen reingehören, muss die Lib doch eh immer 
neu übersetzt werden.

Auf Software-Layer, wo immer alle Gegebenheiten identisch sind, mag das 
ja funktionieren, aber auf Hardware-Ebene sehe ich da keine Chance.
Moderator Persönliche Seite
Jan schrieb:
> Jörg W. schrieb:
>> aber die Idee einer Bibliothek ist es ja
>> gerade, dass sie nicht jedesmal neu übersetzt wird
>
> Wie soll das denn gehen?

Indem man sie vorab compiliert / assembliert, so wie man das schon seit 
50 Jahren macht. ;-)

> In den Libs verwende ich Befehle wie cbi und
> sbi, die via Konstanten auf die richtigen Ports/Pins zugreifen.

Das kannst du in einer (echten) Bibliothek halt nicht tun. Wenn du das 
unbedingt als Bibliothek machen willst und IO-Zugriffe benutzen, dann 
geht das nur über die zugehörigen Speicheradressen (die ja jeder IO-Port 
beim AVR ohnehin besitzt).

Andere Architekturen (wenn du in der AVR-Linie bleibst, bereits beim 
Xmega) sind in der Hinsicht entwas einfacher zu handhaben, da dort 
üblicherweise jedes Peripheral über eine struct angesprochen wird für 
die einzelnen Steuerregister, wobei die verschiedenen Instanzen jeweils 
auf eigene Basisadressen abgebildet sind. Diese lässt sich dann auch 
ganz einfach an Bibliotheksroutinen übergeben, aber auf die very special 
AVR optimization in Form von SBI und CBI kann man auf diese Weise 
natürlich nicht zugreifen.

> Da bei
> jedem Projekt dort andere Zahlen reingehören, muss die Lib doch eh immer
> neu übersetzt werden.

Dann ist es aber keine "Lib", sondern einfach nur ein Stück Programm, 
welches jeweils mit compiliert oder assembliert wird.

Vermeide in diesem Falle einfach, das "Bibliothek" zu nennen, um 
Verwirrung zu vermeiden.
Gast
Jan schrieb:
> Da ich gerade noch andere Möglichkeiten untersuche.... gibt es eine
> einfache Lösung für folgendes Problem?
>
>
1
> .ifdef require_some_code
2
> some_code:
3
> ...
4
> .endif
5
> 
6
> ....
7
> 
8
> .ifdef require_some_other_code
9
> require_some_code = 1
10
> some_other_code:
11
> ...
12
> call some_code
13
> .endif
14
>
>
> ERROR: undefined reference to some_code
>
> Er müsste also weiter oben merken, dass der Code weiter unten benötigt
> wird. Anders gesagt müsste es eine Möglichkeit geben, irgendwas zu
> definieren, was  global gültig wäre. Da es 1001 Möglichkeiten gibt, was
> zu definieren, wollte ich mal fragen, ob da jemand was kennt.

Dann bleibt ja nur noch dieses als potentielle Lösung übrig, wenn man 
mal von einem "Stück dynamisch zusammengesetztem Programm" redet.

Folgender Code funktioniert übrigens problemlos. Ist also nicht so, dass 
das nicht schon irgendwie implementiert wäre:
1
cbio foobar,1
2
foobar=1

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 5 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.