Что такое .cfi и .LFE в ассемблерном коде, созданном GCC из программы c ++?

У меня есть следующий код на C ++

int factorial(int n){

    if(n==0){
        return 1;
    }
    return n*factorial(n-1);

}

int main(void){
    factorial(5);
    return 0;
}

Когда я создаю файл сборки, используя g ++ -S factorial.cpp, я получаю следующее:

    .file   "tail_call_opt.cpp"
    .text
.globl _Z9factoriali
    .type   _Z9factoriali, @function
_Z9factoriali:
.LFB0:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    subl    $24, %esp
    cmpl    $0, 8(%ebp)
    jne .L2
    movl    $1, %eax
    jmp .L3
.L2:
    movl    8(%ebp), %eax
    subl    $1, %eax
    movl    %eax, (%esp)
    call    _Z9factoriali
    imull   8(%ebp), %eax
.L3:
    leave
    ret
    .cfi_endproc
.LFE0:
    .size   _Z9factoriali, .-_Z9factoriali
.globl main
    .type   main, @function
main:
.LFB1:
    .cfi_startproc
    .cfi_personality 0x0,__gxx_personality_v0
    pushl   %ebp
    .cfi_def_cfa_offset 8
    movl    %esp, %ebp
    .cfi_offset 5, -8
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $16, %esp
    movl    $5, (%esp)
    call    _Z9factoriali
    movl    $0, %eax
    leave
    ret
    .cfi_endproc
.LFE1:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
    .section    .note.GNU-stack,"",@progbits

Я могу следовать большей части этого, но что такое назначение частей .cfi и .LFE? Где я могу узнать больше о сборке, созданной gcc?

33
задан shuttle87 25 August 2010 в 10:08
поделиться

1 ответ

Эти директивы предписывают газу выдавать теги информации о кадре вызова Dwarf, которые, по-видимому, используются для восстановления трассировки стека, когда указатель кадра отсутствует. В вашем случае присутствует указатель кадра, поэтому я думаю, что его можно использовать для выполнения раскручивания во время обработки исключений. Такой механизм имеет меньше накладных расходов, чем старый sjlj (setjump/longjump). См. здесь, а также связанную спецификацию Dwarf.

Что касается меток .Lxx, префикс .L указывает, что метка является локальной для этого файла и поэтому не будет конфликтовать с метками с таким же именем в других файлах. GCC обычно использует .L для автоматически сгенерированных ярлыков. В этом случае, скорее всего, «FB» означает «начало функции», а «FE» означает «конец функции».

54
ответ дан 27 November 2019 в 18:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: