C Выпуск этикеток в сборке

В настоящее время я начинающий с ассемблера и изучаю, как использовать ассемблер, встроенный в C, для класса. При этом у меня возникают трудности с этой конкретной ошибкой при компиляции моего файла:

/tmp/cckHnU89.s: Сообщения ассемблера:
/tmp/cckHnU89.s:550: Ошибка: символ `.L16'уже определен
/tmp/cckHnU89.s:571: Ошибка: символ `.L18'уже определен
/tmp/cckHnU89.s:576: Ошибка: символ `.L17'уже определен

Я попытался заменить имена меток другими именами, поскольку из файла.s заметил, что метки.L16, .L17 и.L18 используются в моем основном методе, а также в одной из моих функций. Тем не менее, когда я это сделал, у меня просто возникла ошибка сегментации при запуске программы. Есть ли способ изменить имена меток или что-то еще, чтобы исправить, что, по-видимому, конфликт имен?

Что касается моего процессора, я использую процессор Intel Pentium T4500, и я компилирую с gcc версии 4.4.3. Мой код содержит более 300 строк для встроенной части сборки, поэтому я буду жалеть того, кто это читает. По сути, я просто ищу общий ответ о том, как обычно можно исправить конфликт имен, который приводит к ошибке выше. Любое понимание будет с благодарностью.

1 ответ

Решение

Моя догадка здесь (и я только что проверил это с g++ -S а также gcc -S) что ваши собственные метки точно имитируют схему именования (.L<num>) для меток, автоматически назначаемых ассемблерному коду в GCC.

Сделайте следующее:

# 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 в полученном файле ассемблера.

Другие вопросы по тегам