C内联汇编标签问题 [英] C Inline Assembly label issue

查看:118
本文介绍了C内联汇编标签问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前是汇编的总入门者,正在学习如何在课程中使用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++ -Sgcc -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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆