【问题标题】:C Inline Assembly label issueC 内联汇编标签问题
【发布时间】:2012-04-22 06:46:37
【问题描述】:

我目前是汇编的初学者,并且正在学习如何将汇编与 C 内联用于课程。话虽如此,我在编译文件时遇到了这个特殊错误:

/tmp/cckHnU89.s:汇编程序消息: /tmp/cckHnU89.s:550:错误:符号“.L16”已定义 /tmp/cckHnU89.s:571:错误:符号“.L18”已定义 /tmp/cckHnU89.s:576:错误:符号“.L17”已定义

我尝试用其他名称替换标签名称,因为我从 .s 文件中注意到标签 .L16、.L17 和 .L18 用于我的主要方法以及我的一个函数中。但是,什么时候我刚刚因运行程序而出现分段错误。有没有办法更改标签的名称或其他东西来解决显然似乎是命名冲突的问题?

就我的 CPU 而言,我正在运行 Intel Pentium T4500 处理器,并且正在使用 gcc 版本 4.4.3 进行编译。我的代码是 300 多行的内联汇编部分,所以我会饶恕任何阅读此内容的人。本质上,我只是在寻找一个一般性的答案,说明人们通常如何解决产生上述错误的命名冲突。任何见解将不胜感激。

【问题讨论】:

  • 你能告诉我们相关的代码吗?很难说我们是否无事可做。
  • 除了代码之外,请告诉我们您正在为什么 CPU 编译以及您正在使用什么 C 编译器。
  • 不要认为这值得一票否决:(1)这是提供必要信息的诚实尝试,(2)它解释了已经尝试解决问题的方法,(3)它要求一个具体的问题。

标签: c assembly inline-assembly


【解决方案1】:

我的预感是(我刚刚使用g++ -Sgcc -S 验证了这一点)您自己的标签完全模仿了自动分配给 GCC 中的汇编代码的标签的命名方案 (.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 开头的名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2011-05-06
    • 2012-07-31
    • 1970-01-01
    • 2010-11-24
    相关资源
    最近更新 更多