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.

4

1 回答 1

2

我的预感是(我刚刚用g++ -S和验证了它gcc -S)您自己的标签完全模仿了.L<num>自动分配给 GCC 中的汇编代码的标签的命名方案 ( )。

请执行下列操作:

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

...然后cat(或less)生成的.s文件(相同的基本名称,.s后缀,例如source.s)。您会发现该方案的许多标签 ( .L<num>)。现在,如果您自己创建的内联程序集包含与已经自动创建的标签(来自您的 C 代码)相同的名称,那显然会导致冲突。

所以要点:不要.L<num>用作标签的命名方案,因为它会发生冲突。

一般来说,以开头的名字.L似乎在这里自找麻烦。


示例 ( test.cpp),编译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;
}

在 x64 上编译(的内容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

.L观察生成的汇编文件中以开头的名称。

于 2012-04-10T01:03:09.983 回答