正在声明变量指令

时间:2009-06-02 14:23:25

标签: c++

使用高级语言(如c ++,一个显式指令)声明/赋值变量?

e.g。 x = 5;

它将由加载程序处理,并作为状态信息处理,是否正确?

它不是一个指令,而是一个状态对象,而不是类似for循环的东西,它是一个指令,它使它成为cpu的方式?

编辑:好的,澄清一点。我不是在谈论优化。没有假设。我正在以可执行文件格式讨论已编译程序的最终结果。在编译器决定不使用MOV指令的情况下,数据5是否存在于可执行文件数据段或其他地方?

5是否可以作为数据而不是指令存在,以后将数据加载到内存中?或者,通常,当程序执行时,x = 5将导致mov指令。

8 个答案:

答案 0 :(得分:4)

您是否在询问变量声明是否会以与添加或删除相同的方式转换为汇编指令?如果是这样,那么一般的答案就是没有直接转换成汇编。

可能存在便于声明变量的指令,例如更新堆栈指针以为变量腾出空间。但是没有x86汇编指令说明在堆栈上声明这种类型的变量。

我的大部分经验都是使用x86和amd64芯片,因此可能会有其他处理器上的指令,但我不知道它们(但如果确实存在则会很好奇地阅读它们)。

变量赋值有点不同。 x = 5的一般情况将转换为某种类型的汇编指令(例如,将值写入寄存器)。然而,使用C ++很难具体,因为有许多优化和芯片特定设置可能导致特定行在机器代码中没有转换。

答案 1 :(得分:3)

这取决于它的使用方式。

通常,编译器会尽量使每一行都具有低影响力。

如果只在一个地方使用它,你可以打赌你的按钮在机器代码中硬编码,而不是在堆栈上浪费空间。

如果它用于数学或算法运算,并且其值可能会改变,则可以在堆栈上分配变量的空间。然后,如果它经常使用,编译器可能只是将它保留在寄存器中。

答案是:取决于。编译它并使用调试器的机器代码窗口查看结果。

一种可能的实际翻译:

MOV AX, 5

答案 2 :(得分:1)

使用汇编语言通常,mov指令将用于将5加载到表示x的寄存器,堆栈变量或堆变量中。

但是优化器可以决定只使用它作为一个常量值(比如#define),或者如果它没有被使用它可以决定完全删除它并且它决定放置它的位置(寄存器,堆栈变量,堆)

所以,我希望它能回答你的问题,但正如你所看到的,在C ++中分配一个变量抽象了很多东西,这非常好!

仅供参考:我研究了大量的编译器程序集输出。 在这篇文章中,赋值操作优化为程序集OR操作,这非常好: Which is more readable (C++ = )

答案 3 :(得分:1)

这取决于编译器及其执行的优化。如果它执行死存储消除,那么它可能会省略发送汇编代码写入变量。考虑

for(.....) i+= n;
i = 1;
return i;

可以很容易地优化到这个,因为i的着作无论如何都会被后来的作业覆盖

i = 1;
return 1;

如果没有发生1到i的赋值并且循环将运行m次,编译器可以将其优化为

i += n * m;
return i;

如果i是本地的,并且不会更改任何全局状态,则完全包括i的优化增量(以及前面的示例)。如果i具有volatile限定类型,则编译器需要省略这些优化。它必须按语言规范描述的每一步完成。但即便如此,不同的编译器也可能根据目标处理器的功能生成不同的汇编器/指令。

答案 4 :(得分:1)

通常,您无法知道编译器如何将C ++指令转换为汇编指令。从C ++的角度来看,声明包含赋值的变量(如“int x = 5;”)是一条指令。如果您在调试器中单步执行程序,它将在该行停止。但谁知道编译器会用它做什么。 (对于您所知道的所有内容,整个变量可能会被优化掉。)

答案 5 :(得分:1)

在编译时,链接时间,加载时间和执行时间完全取决于各种事情。甚至不保证实现内存中可识别为x的任何内容。 C ++标准描述了一些内存布局和运行时约束,但它只是为了特殊性:它还定义了可观察行为,并明确表示如果所有可观察行为都匹配(“as-if”规则),实现可以随心所欲地执行

这意味着唯一合理的答案将基于实际执行的内容,答案取决于它。

为什么您想知道某些特定代码行是否转换为某些特定的机器代码?如果你说清楚,也许我们可以回答一个对你有用的问题。

答案 6 :(得分:1)

你没有提到x是哪种类型。如果x不是pod类型,并且它有一个接受int的构造函数,而不是

x = 5

可能有其他效果,而不是'存储5某处',因为语法似乎意味着。

#include <iostream>

int i;

class X {
  int _y;
public:
  X(int y) : _y(y) {
    i ++;   // changes a global variable
    std::cout << "got " << y << std::endl;  // does IO
  };
};

现在

X x = 5;

具有完全不同的含义。所以我会说,一般来说,在c ++ x = 5中语句与其他语句一样,因为它可以产生任何副作用(例如在我的例子中:更改全局状态或执行IO)。

答案 7 :(得分:0)

如果你的变量是基本类型(int,char等):

对于全局或静态变量,没有。这只是BSS或DATA段中的一个条目(取决于它是否已初始化),不需要可执行代码。当然,除非必须在运行时评估初始化程序。

对于局部变量,如果它没有初始化,通常第一个意味着汇编指令,其他则不是。那是因为它们的空间分配通常是为堆栈指针添加一个偏移量(事实上,减去 - 堆栈向后增长)。声明第一个int变量时,会生成“ADD SP,4”;对于第二个,它只是改为“ADD SP,8”。此指令不在您声明变量的位置,而是在函数begin处,因为必须在那里分配局部变量的所有堆栈空间。

如果在创建时初始化局部变量,那么您将有一条MOV指令将值加载到堆栈中的位置。该指令与声明的位置相同,与其余代码相关。

这些局部变量规则假设没有优化。一种常见的优化形式是使用CPU寄存器作为变量,在这种情况下不需要分配,但初始化将生成指令。此外,有时这些寄存器必须保留其值,因此您将在开头看到PUSH指令,在函数末尾看到POP。

当没有构造函数(或构造函数被内联)时,对象的规则要复杂得多,但是类似的逻辑适用。当你有一个非内联构造函数时,你当然至少需要一条指令来进行调用。