可变大小堆栈框架的组装(关于局部变量的堆栈)

时间:2018-11-10 17:10:25

标签: c assembly stackframe

long vframe(long n, long idx, long *q){
    long i;
    long *p[n];
    p[0] = &i;
    for(i=1; i<n; i++)
        p[i]=q;
    return *p[idx];
}

我具有vframe函数并生成了这样的汇编代码

1: vframe:
2:    pushq    %rbp
3:    movq     %rsp, %rbp
4:    subq     $16, %rsp
5:    leaq     22(, %rdi, 8), %rax      # I think the number 22 is vary from machine and OS
6:    andq     $-16, %rax       
7:    subq     %rax, %rsp
8:    leaq     7(%rsp), %rax
9:    shrq     $3, %rax
10:   leaq     0(, %rax, 8), %r8
11:   movq     %r8, %rcx
................................
12: L3:
13:   movq     %rdx, (%rcx, %rax, 8)
14:   addq     $1, %rax
15:   movq     %rax, -8(%rbp)
16: L2:
17:   movq     -8(%rbp), %rax
18:   cmpq     %rdi, %rax
19:   jl       L3
20:   leave
21:   ret

如果我们看到从8到11的行,我们没有将p的地址压入堆栈,但是汇编已经假定&p [0]在%rsp中,因为leaq 0(,%rax,8),%r8表示指令将%r8设置为&p [0] (实际上,我通过检查自己的编译器来检查变量是否已移至堆栈 就像movq $ 0x1,-0x8(%rbp),但我找不到&p [0])

如果我们希望某些参数不被破坏,则推送一些寄存器,并将被调用方保存的寄存器移到推送的寄存器中。但是,在这种情况下,似乎不是。  这段代码中是否还有其他有关局部变量的约定,例如i和&p [0]?我的意思是即使我们没有将&p [0]压入堆栈,为什么&p [0]也位于%rsp中?

1 个答案:

答案 0 :(得分:2)

编译器在内部跟踪每个局部变量的偏移量,包括p。它不需要在堆栈上存储局部变量的地址。在这种情况下,它知道p为(%rsp)。

此代码除了使用rbp之外,不使用任何保留呼叫的寄存器,因此它是唯一保存的寄存器。