2012-04-09 4 views
2

Ich bin derzeit ein Anfänger mit Montage und ich lerne, wie man Assembly Inline mit C für eine Klasse verwendet. Davon abgesehen, ich habe eine harte Zeit mit diesem Fehler habe, wenn ich meine Datei bin Kompilieren:C Inline-Assembly-Label Ausgabe

 
/tmp/cckHnU89.s: Assembler messages: 
/tmp/cckHnU89.s:550: Error: symbol `.L16' is already defined 
/tmp/cckHnU89.s:571: Error: symbol `.L18' is already defined 
/tmp/cckHnU89.s:576: Error: symbol `.L17' is already defined 

Ich habe versucht, die Namen der Etiketten mit anderen Namen zu ersetzen, da ich von der .s-Datei festgestellt, dass Die Labels .L16, .L17 und .L18 werden sowohl in meiner Hauptmethode als auch in einer meiner Funktionen verwendet. Als ich das tat, endete ich jedoch mit einem Segmentierungsfehler beim Ausführen des Programms. Gibt es eine Möglichkeit, die Namen der Etiketten oder etwas anderes zu ändern, das anscheinend ein Namenskonflikt zu sein scheint?

Soweit meine CPU, ich bin mit einem Intel Pentium T4500 Prozessor und ich kompiliere mit GCC-Version 4.4.3. Mein Code ist mehr als 300 Zeilen für den Inline-Montageteil, also werde ich denjenigen verschonen, der dies liest. Im Grunde suche ich nur nach einer allgemeinen Antwort darauf, wie man normalerweise den Namenskonflikt behebt, der den obigen Fehler hervorbringt. Alles, was dazu gehört, wird sehr geschätzt.

+6

Können Sie uns den entsprechenden Code zeigen? Etwas schwer zu sagen, ob wir nichts weiter machen können. – Mysticial

+2

Bitte geben Sie neben dem Code an, für welche CPU Sie kompilieren und welchen C-Compiler Sie verwenden. – user9876

+3

Glauben Sie nicht, dass dies einen Downvote verdient: (1) es ist ein ehrlicher Versuch, die notwendigen Informationen zu liefern, (2) es erklärt, was bereits versucht wurde, das Problem anzugehen, (3) es stellt eine spezifische Frage. –

Antwort

2

hier Meine Vermutung ist (und ich überprüft sie nur mit g++ -S und gcc -S), dass Sie Ihre eigenen Etiketten genau das Namensschema ahmen (.L<num>) für Etiketten in Assemblercode in GCC automatisch zugewiesen.

Gehen Sie wie folgt:

# for C: 
gcc -S source.c 
# for C++ 
g++ -S source.cpp 

... und dann cat (oder less) die resultierende .s Datei (denselben Basisnamen, .s Suffix, zum Beispiel source.s). Sie werden zahlreiche Etiketten dieses Schemas finden (.L<num>). Nun, wenn Sie selbst Inline-Assembly erstellen, das die gleichen Namen enthält wie bereits automatisch erstellte Labels (aus Ihrem C-Code), würde das natürlich zu Konflikten führen.

Also das Wesentliche: Verwenden Sie nicht .L<num> als Ihr Benennungsschema für Etiketten, weil es zusammenstoßen wird.

Allgemein scheinen Namen beginnend mit .L hier Probleme zu suchen.


Beispiel (test.cpp), kompilieren mit g++ -S test.cpp:

#include <cstdio> 

int main(int argc, char**argv) 
{ 
     switch(argc) 
     { 
       case 0: 
         printf("test 0\n"); 
         break; 
       case 1: 
         printf("test %d\n", argc); 
         break; 
       case 2: 
         printf("test %d -> %s\n", argc, argv[0]); 
         break; 
       default: 
         printf("Default\n"); 
         break; 
     } 
     return 0; 
} 

Zusammengestellt auf x64 (Inhalt test.s):

 .file "test.cpp" 
     .section  .rodata 
.LC0: 
     .string "test 0" 
.LC1: 
     .string "test %d\n" 
.LC2: 
     .string "test %d -> %s\n" 
.LC3: 
     .string "Default" 
     .text 
.globl main 
     .type main, @function 
main: 
.LFB0: 
     .cfi_startproc 
     .cfi_personality 0x3,__gxx_personality_v0 
     pushq %rbp 
     .cfi_def_cfa_offset 16 
     movq %rsp, %rbp 
     .cfi_offset 6, -16 
     .cfi_def_cfa_register 6 
     subq $16, %rsp 
     movl %edi, -4(%rbp) 
     movq %rsi, -16(%rbp) 
     movl -4(%rbp), %eax 
     cmpl $1, %eax 
     je  .L4 
     cmpl $2, %eax 
     je  .L5 
     testl %eax, %eax 
     jne  .L8 
.L3: 
     movl $.LC0, %edi 
     call puts 
     jmp  .L6 
.L4: 
     movl -4(%rbp), %eax 
     movl %eax, %esi 
     movl $.LC1, %edi 
     movl $0, %eax 
     call printf 
     jmp  .L6 
.L5: 
     movq -16(%rbp), %rax 
     movq (%rax), %rdx 
     movl -4(%rbp), %eax 
     movl %eax, %esi 
     movl $.LC2, %edi 
     movl $0, %eax 
     call printf 
     jmp  .L6 
.L8: 
     movl $.LC3, %edi 
     call puts 
.L6: 
     movl $0, %eax 
     leave 
     ret 
     .cfi_endproc 
.LFE0: 
     .size main, .-main 
     .ident "GCC: (Debian 4.4.5-8) 4.4.5" 
     .section  .note.GNU-stack,"",@progbits 

die Namen Beobachten mit .L in der resultierenden Assembler-Datei starten .

+0

Ok, das macht Sinn. Vielen Dank! –

+0

@Tyler: zögern Sie nicht zu fragen oder zu akzeptieren, wenn Sie die Antwort verifiziert haben ... – 0xC0000022L