2012-04-09 18 views
2

現在、私はアセンブリの初心者です。クラスに対してインラインでCを使用する方法を学習しています。言われていること、私は私のファイルにコンパイルしていたとき、私はこの特定のエラーで苦労している:Cインラインアセンブリのラベルの問題

 
/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 

を私はその.Sファイルから気づいたので、他の名前のラベルの名前を置き換えてみましたラベル、.L16、.L17、および.L18は私の主要な方法と私の関数の一つで使われています。しかし、いつ私はちょうどプログラムを実行することからセグメンテーションフォールトに終わったのですか?明らかに命名の競合と思われるラベルの名前や修正すべきものを変更する方法はありますか?

私のCPUのところでは、Intel Pentium T4500プロセッサを実行していますが、gccバージョン4.4.3でコンパイルしています。私のコードはインラインアセンブリー部分の300行以上ですので、これを読んだ人は誰でも余裕ができます。本質的には、上記のエラーを引き起こす命名の競合をどのように修正するのかという一般的な答えを探しています。何か洞察力が大いに評価されるだろう。ここ

+6

関連するコードを表示できますか?私たちに何もない場合は、伝えるのは難しいです。 – Mysticial

+2

コードだけでなく、コンパイルするCPUと使用しているCコンパイラについて教えてください。 – user9876

+3

これは、(1)必要な情報を提供するための正直な試み、(2)問題に対処するために既に試行されたことを説明すること、(3)特定の質問をすること、 –

答えて

2

私の勘では、独自のラベルを正確に自動的にGCCにアセンブラコードに割り当てられたラベルの名前付けスキーム(.L<num>)を模倣していること(と私はちょうどg++ -Sgcc -Sでそれを検証する)です。

は、次の操作を行います(たとえば、同じベース名、.sサフィックス、source.s

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

...そしてcat(またはless)結果.sファイルを。あなたはそのスキームの多くのラベル(.L<num>)を見つけるでしょう。今では、自動的に作成されたラベル(Cコードから)と同じ名前を持つインラインアセンブリを自分で作成すると、明らかに衝突につながります。

したがって、gist:ラベルの命名規則として.L<num>を使用しないでください。これは衝突するためです。

から始まる名前は、.Lで始まります。


例(test.cpp)、g++ -S test.cppでコンパイル:x64でコンパイル

#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; 
} 

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で始まる名前を守っ。

+0

わかりました。ありがとう! –

+0

@タイラー:答えを確認したら、お気軽にご相談ください。 – 0xC0000022L