Gcc 常量以内联方式显示在.text中,而不是从内存加载
我们基本上是在sparc体系结构中工作,并使用gcc编译代码 我们在代码中使用了一些常量,但编译器并没有为其中一些常量分配内存,而是优化并使其成为代码的一部分 比如说Gcc 常量以内联方式显示在.text中,而不是从内存加载,gcc,assembly,embedded,ada,sparc,Gcc,Assembly,Embedded,Ada,Sparc,我们基本上是在sparc体系结构中工作,并使用gcc编译代码 我们在代码中使用了一些常量,但编译器并没有为其中一些常量分配内存,而是优化并使其成为代码的一部分 比如说 cHello : CONSTANT INTEGER_16 := 16#FFFE#; a = cHello [ cHello is a constant ]; 大会情况如下 set 16#FFFE#, %g1 sthw %g1, [%g2] 编译器正在将cHello的值内联到代码(.text)中,而不是从内存中加载 如何使编译器
cHello : CONSTANT INTEGER_16 := 16#FFFE#;
a = cHello [ cHello is a constant ];
大会情况如下
set 16#FFFE#, %g1
sthw %g1, [%g2]
编译器正在将cHello的值内联到代码(.text)中,而不是从内存中加载
如何使编译器从内存中加载常量,而不是将其内联
编辑:语言是Ada
我为什么关心:
这就是问题所在,我们有一个嵌入式系统,我们的代码实际上是从RAM运行的,我们希望常量可以修改。我们不想制造它。数据,因为那样我们就有了它的两个副本;通电时,它们被复制到可变RAM区域。因此,在这种情况下,常数更好。加上我们执行的RAM被写锁定。所以我们解锁它,然后写入RAM代码 它正在按预期工作。常量变量是在.text(或任何const部分)中分配的,但是您希望使用RAM作为闪存,因为RAM是有值的。
无论如何,如果您确实想使用RAM分配常量值,您可以通过链接器在RAM中创建一个新的节(
.myowncont
),并将您的常量变量声明为\uu属性((.section(.myownconts)))
,它正在按预期工作。常量变量是在.text(或任何const部分)中分配的,但是您希望使用RAM作为闪存,因为RAM是有值的。
无论如何,如果您确实想使用RAM分配常量值,您可以通过链接器在RAM中创建一个新的节(
.myowncont
),并将您的常量变量声明为\uuuu属性((.section(.myownconts”))
,这个答案的语法将采用最近的(GNAT,Ada2012)编译器,但我毫不怀疑你也可以用布拉格语做同样的事
通过观察,GNAT会将常量转换为直接文本(如果它能看到)
GNAT不允许您将变量设置为常量和易变变量
我发现强制从存储中提取常量的唯一方法是通过让编译器导入变量来愚弄编译器:
带接口;
包Prakhar_常量为
私有的
Chello:constant Interfaces.Integer_16:=16#7FFE#
具有
出口,,
外部名称=>“常数”;
end Prakhar_常数;
然后
带接口;
使用Prakhar_常数;——这样活页夹就知道要包括它
Prakar是
Chello:constant Interfaces.Integer_16
具有
进口,,
惯例=>Ada,
外部名称=>“常数”;
A:Interfaces.Integer_16;
开始
A:=CHello;
结束普拉哈;
我认为您不必为
volatile
(除非您打算在执行过程中更改“常量”)这个答案的语法将假定是一个最近的(GNAT,Ada2012)编译器,但我毫不怀疑您可以对pragmas做同样的事情
通过观察,GNAT会将常量转换为直接文本(如果它能看到)
GNAT不允许您将变量设置为常量和易变变量
我发现强制从存储中提取常量的唯一方法是通过让编译器导入变量来愚弄编译器:
带接口;
包Prakhar_常量为
私有的
Chello:constant Interfaces.Integer_16:=16#7FFE#
具有
出口,,
外部名称=>“常数”;
end Prakhar_常数;
然后
带接口;
使用Prakhar_常数;——这样活页夹就知道要包括它
Prakar是
Chello:constant Interfaces.Integer_16
具有
进口,,
惯例=>Ada,
外部名称=>“常数”;
A:Interfaces.Integer_16;
开始
A:=CHello;
结束普拉哈;
我认为您不必为
volatile
(除非您打算在执行过程中更改“常量”)您可以尝试使用别名常量:
cHello : aliased constant Interfaces.Integer_16 := 16#FFFE#;
您可以尝试使用别名常量:
cHello : aliased constant Interfaces.Integer_16 := 16#FFFE#;
我认为应该在独立asm或C文件中定义常量的值。这是一种有保证的方法,可以阻止编译器在任何地方内联值,即使是在进行链接时间优化的情况下,也不会使用像volatile
这样效率低下的东西。i、 Ada编译器在任何源文件中都根本看不到常量的值
我不知道Ada,但是C等价物应该是extern const int my_const然后在一个单独的常量.S
文件中使用.section.rodata
/我的常量:.long 0x12345
。或者使用自定义节和链接器脚本将可修改常量放置在二进制文件中特定的位置
有关将Ada与C或asm接口的更多信息,请参阅。它提供了将符号定义导入C或从C导出符号定义的示例(并且C和asm之间的映射非常简单,因此即使使用asm创建对象文件,您也可以告诉Ada它是C。)
理想情况下,您可以声明My_Num
,使Ada编译器知道它是一个常量这将它声明为一个普通的全局变量(外部定义使用Ada_my_num
C符号名)。
这与@Jose的答案所建议的非常相似,只是使用独立的asm对编译器隐藏值
您希望编译器能够尽可能地优化。i、 假设这个“变量”的值在程序的生命周期内不会改变,因此它可以在函数开始时将其加载到寄存器中,并假设对非内联函数的调用不能改变它。或者避免重做涉及它的计算(),因此如果您的源代码
const int my_const1, my_const2;
static const int my_static = 123; // a small constant that works as an immediate
int foo(int x) {
return x + my_static;
}
retl
add %o0, 123, %o0 # branch-delay slot
int one_constant(int x) {
return x + my_const1;
}
sethi %hi(my_const1), %o1
ld [%o1+%lo(my_const1)], %o1
retl
add %o1, %o0, %o0