[英]Another question about C compiler asm output
很快你的问题。 当我在C中存储一些自动变量时,asm输出是这样的: MOV ESP+4,#25h
,我只是想知道为什么编译器无法计算ESP+4
地址。
我想通了,我真的找不到理由。 我的意思是,不是编译器知道esp值吗? 它应该是。 当使用另一个目标文件时,这也不应该是问题,因为变量可以只是由地址表示并在以后链接,当所有自动变量都已知时,因此可以分配正确的地址。 谢谢。
不,编译器在运行时不知道ESP
的值 - 它是堆栈指针。 每次调用函数时它都可能不同。 也许最简单的例子是递归函数 - 每次调用自身时,堆栈会更深入地适应新调用的局部变量。 每个堆栈帧都有自己的局部变量,每个堆栈帧都位于堆栈的不同位置,因此有自己的地址(通常在ESP
)。
不,它无法提前知道esp
的价值。
以递归函数为例,即。 一个自称的函数。 假设这样的函数有几个通过堆栈传入的参数。 这意味着每个参数在堆栈上占用一些空间,从而改变esp
寄存器的值。
现在,当输入函数时, esp
的确切值将取决于函数先前调用自身的次数,编译器无法在编译时知道这一点。 如果你怀疑这一点,请采取如下函数:
void foobar(int n)
{
if (rand() % n != 17)
foobar(n + 1);
}
编译器无法提前足够聪明地判断该函数是否会再次调用自身。
如果编译器想要提前确定esp
,则实际上必须为esp
每个可能值创建函数的版本。
以上说明仅考虑一个功能。 在现实世界的场景中,程序具有许多彼此相互依赖的功能,这导致相当复杂的“调用图”。 这与(以及其他)不可预测的程序逻辑一起意味着编译器必须创建每个函数的大量版本,只是为了优化esp
- 这显然没有意义。
PS:现在别的了。 实际上你根本不需要优化[esp+N]
,因为它不应该比简单的[esp]
花费更多的CPU时间......至少在Intel Pentium CPU上没有。 你可以说它们已经包含了针对这个甚至更复杂场景的优化。 如果你有兴趣在Intel的CPU,我建议你查查称为MOD R / M和机器指令的SIB字节的东西的文档,例如这里的SIB字节或这里或,当然,在英特尔的官方CPU开发人员文档。
堆栈指针无法在编译时计算。 举一个简单的例子,为什么这是不可能的,只需考虑一个递归函数:同一个变量为每个调用都有不同的地址,但它始终与运行的代码相同。
不,编译器不会提前知道值。 在一些非常基本的程序中(从main
到任何其他特定函数只有一个可能的“路由”被调用)它可以 ,但我不知道编译器试图计算这个。 如果您有任何递归,或者从多个位置调用函数,则堆栈指针将具有不同的值,具体取决于它的调用位置。
没有太多的点在任何情况下这样做-由于堆栈指针是如此频繁使用,大部分的CPU的设计使间接从栈指针非常有效的解决。 实际上,它通常比提供绝对地址更有效。
这对堆栈的工作方式来说非常重要。 为了自己解释一下,想象一下如何实现递归函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.