Das zusätzliche "leading underscore" in Symbolnamen wird von manchen ABIs vorgeschrieben, d.h. ein Symbolname hat 1 Underscore mehr als auf anderen Plattformen.
So wird ein Object (Funktion oder Variable), das auf C-Ebene sym heißt, im Assembly als _sym ausgegeben. Beispiel C:
1 |
int var;
|
2 |
|
3 |
int fun (void)
|
4 |
{
|
5 |
return var;
|
6 |
}
|
wird assembliert mit x686-w64-mingw32-gcc (unbedeutende Teile entfernt):
1 |
.globl _fun
|
2 |
_fun:
|
3 |
movl _var, %eax
|
4 |
ret
|
5 |
|
6 |
.globl _var
|
7 |
.bss
|
8 |
_var:
|
9 |
.space 4
|
Und das gilt dann auch für C++:
fun wird in MinGW als __Z3funv assembliert, für x86_64-linux-gnu hingegen als _Z3funv.
Was unter MinGW auffällt, ist dass Labels zum Beispiel "L5" heißen, was ohne Underscore dann mit einem Objekt namens "L5" verwechselt werden würde. Das ABI vermeidet dies, indem Symbole von Hochsprache einen "_" verpasst bekommen.
Auf anderen Plattformen werden Labels z.B. als ".L5" benamt; keine Ahnung warum das unter Windows nicht gemacht wird / wurde. Evtl. kann ein Archäologe da mehr zu sagen.
Um in einem Project C und C++ zusamme zu nutzen müssen die C-Teile als extern "C" Linkage implementiert sein, im obigen Beispiel etwa
1 |
extern "C" int fun (void);
|
Um Assembly und C/C++ zusammen zu verwenden, muss im Assembly die Naming Convention dem ABI folgen. Es ist zwar möglich, den Assembly Name mit GCC anzugeben, aber dabei wird man nach Möglichkeit dem ABI folgen, hier als GCC Erweiterung:
1 |
int fun (void) __asm ("_bar");
|
Schließlich gibt es je nach Host noch -f[no-]leading-underscore, aber was ABI angeht gilt das eben gesagte.