它是堆栈框架吗?

Is it a stack frame?

我不明白为什么 gcc 甚至为此代码触及 %esp:

int foo(char *);

int bar(char** a)
{
    if (!a[1]) {
        return 1;
    }

    if (foo(a[1]) == -1) {
        return 1;
    }

    return 0;
}

生成 -O2:

bar:
.LFB0:
        .cfi_startproc
        movq    8(%rdi), %rdi
        movl    , %eax
        testq   %rdi, %rdi
        je      .L7
        subq    , %rsp
        .cfi_def_cfa_offset 16
        call    foo
        cmpl    $-1, %eax
        sete    %al
        addq    , %rsp
        .cfi_def_cfa_offset 8
        movzbl  %al, %eax
.L7:
        rep ret

而且 clang 通过在开始时将 %rax 推入 %rax 然后将其弹出到 %rdx.

来做一些甚至疯狂的事情

是分配栈帧吗?这与这些 .cfi 指令有关吗?

因为在x64中,栈必须是16字节对齐的,调用指令使栈失衡。这个特定的代码不关心任何事情,但编译器不知道 foo 关心的任何指令。

事实上,它总是在调用时未对齐,应该在序言代码中重新对齐;然而,优化器将 prolog 和 epilog 破坏得面目全非。