我有以下代码
#include<stdio.h>
int adunare(int a,int b)
{
int c=3;
int d=6;
while(c>10) c++;
if(c>15) return a+b+c+d;
else return a+b+c-d;
}
int main()
{
int w=5;
int y=6;
printf("%d",adunare(w,y));
}
我的问题是在汇编中它将变量w,y放在[esp + 24],[esp + 28]。
为什么把变量放在那里?
我知道局部变量总是[ebp -....]。
为什么这里不是[ebp- ..]?
答案 0 :(得分:9)
我知道局部变量总是[ebp -....]
他们不是(我的问题也证明了这一点。)
编译器非常天真地编译是合法的,总是使用帧指针(即使在不执行可变大小堆栈分配的函数中)并且始终将局部放在堆栈中(这绝对不是一个)规则)。在大学的第一年课程中,为了简单起见,有时会假装这是正常的。
通常不使用帧指针,它的工作方式与使用其中的指针大致相同,只是相对于堆栈指针计算偏移量,现在只允许以可预测的方式移动。因为它必须是可预测的(即,引用堆栈槽的每个指令都可以使用常量偏移量来执行此操作),所以此优化不能用于使用alloca
或VLA的函数。在您的示例函数中都没有使用,因此不需要帧指针。
另外一般情况下,你应该不期望局部变量首先对应于特定的堆栈槽,而不管它们是如何被寻址的。在变量的整个生命周期内将变量保存在寄存器中是允许的,常见的,并且通常是好事。特别是如果寿命很短或者使用密度非常高。最重要的是,具有不重叠生命周期的变量可以(并且应该,因为它减少了堆栈大小)共享堆栈插槽,因为在任何一个时刻最多其中一个需要存储的情况(由于假设不重叠的生命时间)。
它还允许从一个堆栈槽到另一个堆栈槽的变量跳转,这可能发生在以允许交换“虚拟”解析的方式交换两个变量时,只需更改变量所在的堆栈槽实际上并没有交换数据。
答案 1 :(得分:1)
这可能是编译器优化。变量不在main
范围内使用,因此直接放在堆栈上,为函数调用做好准备。