首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++/C -assembly级问题

C++/C -assembly级问题
EN

Stack Overflow用户
提问于 2010-12-11 11:49:47
回答 4查看 351关注 0票数 7
  1. 当在函数(C/C++)中使用全局变量时,它是直接从寄存器还是从堆栈中获取?
  2. 为什么绑定循环(对于循环)被认为比非绑定循环具有更大的优化空间(尽管循环/做循环)?
  3. 为什么返回值不如通过引用传递值那么好?

如果可能的话,请给出装配级别的描述。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-12-11 12:50:36

1)全局变量是由链接器静态分配的(它可以是模块基的偏移量,但不一定是固定地址)。不过,函数通常从直接地址读取全局变量,从偏移量+堆栈指针读取本地变量,从偏移量+对象基指针读取类字段。全局变量的值可以缓存在寄存器中供后续读取,除非声明为“易失性”。

2)这实际上不是for/do/while选择的问题,而是计算迭代次数有多容易,以便编译器能够决定是否展开和/或向量化循环和/或并行化。例如,这里编译器将知道迭代的次数:

代码语言:javascript
复制
for( i=0; i<8; i++ ) { j = 1 << i; XXX }

而在这里,它不会:

代码语言:javascript
复制
for( j=1; j<256; j<<=1 ) { XXX }

for循环可能只是更频繁地有一个结构,这对于编译器来说更容易理解。

3)如果它是一个基本类型的值(char/short/int等),则通过引用返回它的速度较慢(尽管有时编译器可以优化它)。但是对于较大的结构,引用/指针可以减少编译器的工作量,如果编译器不能避免创建一些临时副本等,那么它确实会更快。

更新:好的,下面是一个更具体的例子:

代码语言:javascript
复制
#include <stdio.h>

int main( void ) {

  int a,b, i,j,s1,s2;

  a = 123 + printf(""); // unknown in compile time
  s1 = 1; 
  // bit reverse loop v1, gets unrolled
  for( i=0; i<8; i++ ) { j = 1 << i; s1 += s1 + ((a&j)>0); }
  s1 -= 256;

  b = s1 + printf("");
  // bit reverse loop v2, not unrolled
  for( s2=1; s2<256; s2+=s2+(j>0) ) { j = b & s2; b -= j; }
  s2 -= 256;

  printf( "a=%02X s1=%02X s2=%02X\n", a, s1, s2 );
}

gcc/知识分子的Asm清单可在这里找到:http://nishi.dreamhosters.com/u/1.zip

票数 1
EN

Stack Overflow用户

发布于 2010-12-11 11:59:22

1)它将取自作为应用程序负载的一部分而分配的地址。全局变量只是进程虚拟地址空间中的一个地址。如果最近使用了该全局,编译器可能能够将其缓存在寄存器中。

2)他们没有。

3)返回值通常需要数据的副本。如果数据是一个简单的类型(如int或float),那么它可以并且将通过寄存器返回。如果对象太大,无法适应寄存器,那么编译器必须为堆栈上的对象分配空间,然后将返回的数据复制到这个分配的空间中。作为引用传递值通常是通过传递指向数据的指针来实现的。因此,可以通过直接修改该内存地址上的数据来返回该值。没有复制发生,因此它更快。但是,请注意,返回值优化(RVO)可能意味着将返回值作为引用传递不会有任何胜利。同样,A在评论中指出,C++0x的新移动构造函数也可以提供与RVO相同的奖金。

海事组织没有必要用汇编语言的例子来解释其中的任何一个。

票数 4
EN

Stack Overflow用户

发布于 2010-12-11 19:35:03

首先,您还没有指定目标平台、arm、x86、6502、zpu等。

1)在函数(C/C++)中使用全局变量时,它是直接从寄存器还是从堆栈中获取?

您不清楚,因此可以通过值、引用或不传入并直接在函数中使用全局信息。

由值传递的值取决于未指定的代码/编译器/目标。因此,全局的值或地址可以根据编译器/目标的调用约定进入寄存器或堆栈。通过寄存器传入的项有时在堆栈上有占位符,以防函数需要比可用寄存器更多的寄存器。因此,通过值传递全局包含的值,最初可以在寄存器或堆栈中访问该值。

通过引用传递的值与通过值传递的值基本相同,而不是通过寄存器或堆栈传递到全局的地址,这取决于编译器/目标。其不同之处在于,您可以直接从/访问全局的内存位置,但这是通过引用传递的本质。

直接在函数中使用,则取决于代码/编译器/目标是否直接从其固定内存位置访问全局,或者寄存器是否从寄存器加载该内存位置和值。在这种情况下不使用堆栈,所以答案要么是(非堆栈)内存,要么是寄存器。

2)为什么绑定循环(对于循环)被认为比非绑定循环有更大的优化空间(而循环/做循环)?

取决于代码、编译器和目标,我想不出一种比另一种更好的通用情况。

( 3)为什么返回值不如通过引用传递值好?

非常微妙的性能增益,如果有的话。严重依赖于代码、编译器和目标。有些情况下,引用的速度略快一些,而按价值计算的情况则稍快一些。比较两者,差异与地址或数据必须复制到/从寄存器或路径上的堆栈的次数有关。充其量,您可以保存一些mov或加载/存储指令。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4416569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档