3

I'm currently a total beginner with assembly and am learning how to use assembly inline with C for a class. That being said, I'm having a hard time with this particular error when I'm compiling my file:

/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

I tried replacing the names of the labels with other names since I noticed from the .s file that the labels .L16, .L17, and .L18 are used in my main method as well as in one of my functions. However, when did that I just ended up with a segmentation fault from running the program. Is there a way to change the names of the labels or something else to fix which apparently seems to be a naming conflict?

As far as my CPU, I'm running an Intel Pentium T4500 processor and I'm compiling with gcc version 4.4.3. My code is 300+ lines for the inline assembly portion so I'll spare whoever reads this. Essentially, I'm just looking for a general answer on how one would normally fix the naming conflict that produces the error above. Anything insight would be greatly appreciated.

  • 6
    Can you show us the relevant code? Kinda hard to tell if we have nothing to go on. – Mysticial Apr 09 '12 at 23:03
  • 2
    As well as the code, please tell us what CPU you're compiling for and what C compiler you're using. – user9876 Apr 09 '12 at 23:25
  • 3
    Don't think this deserves a downvote: (1) it's an honest attempt to provide the necessary information, (2) it explains what has already been attempted to address the problem, (3) it asks a specific question. – Robert Martin Apr 09 '12 at 23:41

1 Answers1

2

My hunch here is (and I just verified it with g++ -S and gcc -S) that your own labels are exactly mimicking the naming scheme (.L<num>) for labels automatically assigned to assembler code in GCC.

Do the following:

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

... and then cat (or less) the resulting .s file (same base name, .s suffix, e.g. source.s). You will find numerous labels of that scheme (.L<num>). Now, if you yourself create inline assembly containing the same names as already automatically created labels (from your C code), that would obviously lead to clashes.

So the gist: don't use .L<num> as your naming scheme for labels, because it will clash.

Generally names starting with .L seem to ask for trouble here.


Example (test.cpp), compile with 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;
}

Compiled on x64 (contents of 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

Observe the names starting with .L in the resulting assembler file.

0xC0000022L
  • 20,597
  • 9
  • 86
  • 152