gcc中的全局寄存器变量 [英] Global register variables in gcc

查看:302
本文介绍了gcc中的全局寄存器变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我在一次采访中被问及全局变量。我搞砸了,说任何全局变量都会被存储在数据段中。但是后来我被问到有关GCC的情况。在采访之后,我得出结论:gcc支持全局寄存器变量。

  #include< stdio.h> 

寄存器int var asm(ebx); //显式地将全局变量存储在寄存器中
$ b $ int main(void)
{
.......
}

这里是链接
https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars



但是现在我对它的生命期和范围感到困惑,它是否会像正常的全局变量或寄存器变量一样工作?也有任何方法或gcc上的一些命令,以便我们确信编译器不会简单地忽略 register 关键字,并且将以实际存储注册?

解决方案

正如许多人指出的,全局保留寄存器通常是一个坏主意。我相信这里的原意是(来自文档):


这对编程语言
解释器这样的程序很有用,它有几个全局变量这是经常访问

这是否真的有用,或者最终导致更糟的情况可能只是根据具体情况确定。在你的情况下(面试问题),这并不重要。



像这样的声明的范围就是看到声明的所有内容,就像你期望的那样任何全球性声明。

然而,实现有点棘手。同样,从文档中引用:


在某个寄存器中定义一个全局寄存器变量保留
,至少在目前的
编译中
当前编译中的函数未将该寄存器分配给任何其他用途,并且未保存并且
被这些函数恢复。


因此,使用该声明编译的所有代码都将保留该使用的寄存器。但是,如果您链​​接到其他未使用此预留编译的代码,则不会为此目的而保留。



文档给出了qsort的一个很好的例子。如果你的代码是用这个声明编译的,然后它从c运行时调用qsort(这可能不是用这个声明编译的),然后qsort调用回你的代码(用于比较函数),回调函数不能请确保qsort在调用比较函数之前不会跺脚寄存器。



如果调用任何库函数可能会在寄存器上跺脚,该如何工作?同样来自文档:


选择一个通常由您的机器上的函数
调用保存和恢复的寄存器,例程不会破坏它。


即使在那:


从信号
处理程序或从多个控制线程访问全局寄存器变量是不安全的,因为系统
库例程可能暂时将寄存器用于其他事物$

至于你问题的最后部分: p>


编译器不会简单地忽略寄存器关键字并将存储在
实际寄存器中

我不确定你的意思。如果(某种程度上)编译器忽略了 asm(ebx),那么它不会被存储在寄存器中。使用它的全部要点是确保 var 存储在实际的ebx寄存器中。


Recently I was asked about global register variables in an interview.I messed up saying that any global variable will be stored in Data segment.But then i was asked about GCC.After interview i came to conclusion that gcc supports global register variables.

#include<stdio.h>

register int var asm("ebx");  //storing global variable in register explicitly

int main(void)
{
.......
}

Here is link https://gcc.gnu.org/onlinedocs/gcc/Global-Reg-Vars.html#Global-Reg-Vars

But now i am confused about its lifetime and scope and whether it will work as normal global variable or as register variable? Also is there any method or some command on gcc so that we will be sure that compiler will not simply ignore register keyword and will be stored in actual register?

解决方案

As a number of people have pointed out, reserving a register globally is generally a bad idea. I believe the original intent here was (from the docs):

This may be useful in programs such as programming language interpreters that have a couple of global variables that are accessed very often.

Whether this is really useful, or just ends up making things worse can probably only be determined for specific cases. In your case (interview question), that isn't really important.

The scope of a declaration like this is everything that sees the declaration, just as you would expect with any global declaration.

However, implementation is a bit tricky. Again, quoting from the docs:

Defining a global register variable in a certain register reserves that register entirely for this use, at least within the current compilation. The register is not allocated for any other purpose in the functions in the current compilation, and is not saved and restored by these functions.

So, all code that is COMPILED using that declaration will reserve the register for that use. However, if you LINK to other code that was not compiled with this reservation, it will not be reserved for that purpose.

The docs give an excellent example with qsort. If your code is compiled with this declaration, and then it calls qsort from the c runtime (which presumably isn't compiled with this declaration), and then qsort calls back into your code (for the compare function), the callback can't be sure that qsort doesn't stomp on the register before calling your compare function.

How can this ever work if calling any library function can stomp on the register? Again from the docs:

Choose a register that is normally saved and restored by function calls on your machine, so that library routines will not clobber it.

Even at that:

It is not safe to access the global register variables from signal handlers, or from more than one thread of control, because the system library routines may temporarily use the register for other things (unless you recompile them specially for the task at hand).

As for the last part of your question:

compiler will not simply ignore register keyword and will be stored in actual register

I'm not sure what you mean. If (somehow) the compiler ignored the asm("ebx"), then it would NOT be stored in a register. The whole point of using this is to ensure that var is stored in the actual ebx register.

这篇关于gcc中的全局寄存器变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆