2016-07-08 9 views
3

Ich lerne OS-Entwicklung in einer Linux-Umgebung mit GCC. Ich habe in Brans Kernel-Entwicklung gelernt, dass alle Funktionen und Variablennamen in C, wenn sie kompiliert werden, mit einem "_" (Unterstrich) in der entsprechenden Assembly-Quelldatei vorangestellt sind. Aber als ich die Assembly-Quelle eines kompilierten C-Programms durchging, kann ich nicht einmal die "_main" -Funktion finden. Ich führte Folgendes durch.Werden die Funktionen und Variablen mit einem "_" vorangestellt, wenn sie mit gcc kompiliert werden?

cpp Sample.c sample.i

gcc -S sample.I

+1

Sie User-Space-Programm zusammenstellen. Wie bezieht sich das "Kernel" -Tag auf dieses Problem? – Tsyvarev

+0

Verwenden Sie neuere Ressourcen für aktuelle Tools/Software – Olaf

Antwort

5

Dies trifft in den frühen Tagen war. Eine gegebene C-Funktion foo würde im Assembler als _foo erscheinen. Dies wurde gemacht, um Konflikte mit handgenerierten .s Dateien zu vermeiden.

Es wäre auch auf insgesamt 8 Zeichen [eine Linker-Einschränkung] begrenzt.

Dies ist seit Jahrzehnten nicht mehr wahr. Nun haben die Symbole nicht mehr das Präfix _ und können viel länger als 8 Zeichen sein.


UPDATE:

So, heute GCC nicht produzieren ein _ vor Funktionen und Variablen?

In den meisten Fällen, nein. IMO, die Referenz, die Sie an diesem Punkt zitieren, scheint ein wenig veraltet zu sein. Die meisten POSIX-Systeme (z. B. Linux, * BSD) verwenden gcc [oder clang] und sie verlassen die _.

Als ich mit dem Programmieren in C anfing [circa 1981], wurde die _ immer noch benutzt. Dies war in den frühen 1990er Jahren für neuere Systeme (wie Linux) verschwunden. Persönlich habe ich das Präfix _ seither nicht mehr gesehen, aber ich habe [meistens] Linux [und manchmal Cygwin] benutzt.

Einige AT & T Unix-abgeleitete Systeme haben es möglicherweise aus Gründen der Abwärtskompatibilität beibehalten, aber schließlich haben die meisten alle auf "foo is foo" standardisiert. Ich habe keinen Zugriff auf OSX, daher kann ich Johnathans Kommentar dazu nicht ausschließen.

Die _ gab es seit den frühen Tagen von Unix (circa 1970). Dies war vor meiner Zeit, aber, IIRC, Unix wurde ursprünglich in Assembler geschrieben. Es wurde in C umgewandelt. Die _ sollte Funktionen abgrenzen, die entweder in C geschrieben sind, oder asm, die von C-Funktionen aufgerufen werden können.

Diejenigen, die nicht das Präfix hatten, waren "nur asm" [da sie möglicherweise Nicht-Standard-Aufrufkonventionen verwendet haben]. Damals war alles kostbar: RAM, CPU-Zyklen usw.

Also, asm-Funktionen könnten/würden "Tricks" verwenden, um Ressourcen zu schonen. Mehrere asm-Funktionen könnten als Gruppe funktionieren, weil sie voneinander wussten.

Wenn eine bestimmte asm-Funktion von C aus aufgerufen werden könnte, wäre das _ Präfix-Symbol der C-kompatible "Wrapper" dafür [das extra gespeichert/wiederhergestellt im Prolog/Epilog].

Also kann ich einfach die Hauptfunktion eines C-Programms als "Call-Main" statt "Call _main" aufrufen?

Das ist eine ziemlich sichere Wette.

Wenn Sie eine bestimmte Funktion von C aufrufen, wird automatisch das Richtige getan (z. B. Präfix hinzufügen oder nicht).

Es ist nur beim Versuch, eine C-Funktion von Hand generierte Assembler aufrufen, dass das Problem könnte sogar kommen.

Also, für asm, würde ich nur die einfache Sache tun und tun call main. Es wird auf den meisten [wenn nicht allen] Systemen funktionieren.

Wenn Sie Ihren Code auf "proof Kugel" wollte konnte man Ihre asm durch den C-Präprozessor (über eine .S Datei) laufen und tun (zB):

#ifdef C_USES_UNDERSCORE 
#define CF(_x)   _##_x 
#else 
#define CF(_x)   _x 
#endif 

    call CF(main) 

Aber ich denke, das ist Overkill.

Es zeigt auch das ganze Problem mit der _ Präfix Sache. Warum sollte eine Assembler-Funktion auf einem modernen System [mit vielen Speicher- und CPU-Zyklen] wissen müssen, ob eine ABI-kompatible Funktion, die sie aufruft, von C oder von Hand geschriebenen Assembler erzeugt wurde?

+2

Es hängt von der Plattform, mindestens. Unter Mac OS X, wenn ich eine C-Quelldatei 'any_function 'kompiliere.c 'mit der Funktion 'any_function()' enthält die Objektdatei ein Symbol '_any_function' nach' nm -g any_function.o'. –

+0

Also, GCC produziert heute kein _ vor Funktionen und Variablen ri8? –

+0

Also kann ich einfach die Hauptfunktion eines C-Programms als "Call-Haupt" anstelle von "Call _main" ri8 aufrufen? –

1

Wie von Craig beschrieben, ist es eine Konvention, dass moderne Formate/ABIs wie COFF und ELF nicht mehr folgen.

Auf einigen Zielen, die verschiedene ABIs verwenden, wird es immer noch verwendet. Beispiele sind NeXT/OS X Mach-O oder 16- und 32-Bit-Windows. 64-Bit-Windows verwendet den Unterstrich nicht mehr (obwohl GCC dies eine Zeitlang bis 4.5.1 tat).

Darüber hinaus kann der Unterstrich als Teil eines größeren Präfix angezeigt werden. Zum Beispiel __imp_ in __declspec(dllimport) Symbole oder _Z im Itanium ABI.

Wenn Sie aus irgendeinem Grund die Mangelung beeinflussen müssen, bietet GCC eine -f[no]leading-underscore Flagge. Dies wird die ABI-Kompatibilität brechen.


Einige Links: