C内联汇编标签问题 [英] C Inline Assembly label issue
问题描述
我目前是汇编的总入门者,正在学习如何在课程中使用C内联汇编.话虽这么说,但是我在编译文件时遇到了这个特定的错误:
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
我尝试用其他名称替换标签的名称,因为我从.s文件中注意到,标签.L16,.L17和.L18在我的主要方法以及函数之一中都使用了.但是,什么时候才结束运行程序导致的段错误.有没有办法更改标签的名称或其他似乎可以解决命名冲突的问题?
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?
就我的CPU而言,我正在运行Intel Pentium T4500处理器,并且正在使用gcc 4.4.3版进行编译.我的代码是内联汇编部分的300多行代码,因此无论谁读这本书,我都会省去.本质上,我只是在寻找一个一般性的答案,以解决通常会产生上述错误的命名冲突.任何见识将不胜感激.
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.
推荐答案
我的直觉是(我刚刚用g++ -S
和gcc -S
进行了验证),您自己的标签确实在模仿命名方案(.L<num>
),用于在GCC中自动分配给汇编代码的标签.
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.
执行以下操作:
# for C:
gcc -S source.c
# for C++
g++ -S source.cpp
...,然后cat
(或less
)生成的.s
文件(相同的基本名称,.s
后缀,例如source.s
).您会发现该方案的众多标签(.L<num>
).现在,如果您自己创建内联程序集,其中包含与已经自动创建的标签相同的名称(根据您的C代码),那么显然会导致冲突.
... 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.
要点:不要将.L<num>
用作标签的命名方案,因为它会发生冲突.
So the gist: don't use .L<num>
as your naming scheme for labels, because it will clash.
通常以.L
开头的名称似乎在这里引起麻烦.
Generally names starting with .L
seem to ask for trouble here.
示例(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
的内容):
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
在生成的汇编文件中观察以.L
开头的名称.
Observe the names starting with .L
in the resulting assembler file.
这篇关于C内联汇编标签问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!