【问题标题】:assembly for variable-size stack frame(about stack for local variable)可变大小堆栈框架的组装(关于局部变量的堆栈)
【发布时间】:2019-04-13 22:44:36
【问题描述】:
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] (实际上我通过检查我自己的编译器检查变量 i 是否移动到堆栈 像 movq $0x1,-0x8(%rbp) 但我找不到关于 &p[0])

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

【问题讨论】:

  • 不清楚你在问什么。

标签: c assembly stack-frame


【解决方案1】:

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

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

【讨论】:

  • 那我们怎么知道局部变量的偏移量呢?还有其他约定吗?我可以找到一些汇编代码,例如为局部变量 i 和数组 p(subq $16,第 4 行中的 %rsp 和第 7 行中的 subq %rax,$rsp)分配空间,但我不知道它在哪里
  • 没有约定;编译器可以随意布置堆栈帧。要了解编译器做了什么,您可以查看调试信息。一些编译器将 cmets 放在带有偏移量的汇编语言输出中。或者您可以查看汇编代码以检测编译器存储的内容。
  • 例如,通过检查问题中的汇编代码,我可以知道 n 在 rdi 中,而 i 在 -8(rbp) 中
  • (第三种方式是我唯一使用的方式,所以我无法对前两种提供任何建议。)
猜你喜欢
  • 2011-03-22
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 2021-04-07
  • 1970-01-01
  • 1970-01-01
  • 2015-01-03
  • 1970-01-01
相关资源
最近更新 更多