3

私は現在、アセンブリの完全な初心者であり、クラスでCとインラインでアセンブリを使用する方法を学んでいます。そうは言っても、ファイルをコンパイルしているときに、この特定のエラーに苦労しています。

/tmp/cckHnU89.s:アセンブラメッセージ:
/tmp/cckHnU89.s:550:エラー:シンボル`.L16'はすでに定義されています
/tmp/cckHnU89.s:571:エラー:シンボル`.L18'はすでに定義されています
/tmp/cckHnU89.s:576:エラー:シンボル`.L17'はすでに定義されています

.sファイルから、ラベル.L16、.L17、および.L18がメインメソッドと関数の1つで使用されていることに気付いたので、ラベルの名前を他の名前に置き換えてみました。しかし、それを行ったとき、プログラムの実行によるセグメンテーション違反が発生しました。ラベルの名前を変更する方法や、名前の競合と思われる修正方法はありますか?

CPUに関しては、Intel Pentium T4500プロセッサを実行しており、gccバージョン4.4.3でコンパイルしています。私のコードはインラインアセンブリ部分の300行以上なので、これを読む人は誰でも惜しみません。基本的に、上記のエラーを引き起こす名前の競合を通常どのように修正するかについての一般的な答えを探しています。何か洞察をいただければ幸いです。

4

1 に答える 1

2

ここでの私の勘は(そして私はそれをg++ -Sとで検証したばかりです)、あなた自身のラベルがGCCのアセンブラーコードに自動的に割り当てられたラベルgcc -Sの命名スキーム()を正確に模倣していることです。.L<num>

以下をせよ:

# 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 に答える