GCC用C语言嵌入ARM汇编程序(2)

电脑杂谈  发布时间:2020-06-18 11:08:52  来源:网络整理

如果汇编指令修改了内存,但GCC本身不知道,因为在输出部分中没有描述,则需要在修改描述部分中添加“内存”,以告知GCC内存已被修改, GCC知道了这些信息之后,将在该部分指令之前插入必要的指令,并且针对缓存优化的寄存器中的变量值将首先被写回到内存中,如果这些变量将被再次使用稍后,将再次读取它们.

使用“ volatile”也可以达到这个目的,但是我们在每个变量之前添加此关键字,最好使用“ memory”.

++ / cppjs / 2008331 / 107755.html

我最近开始学习C语言,我想记录一下我在学习过程中的一些经验. 让我将其作为我学习经历的笔记. 如果您不小心阅读了这些文章,则可以帮助我指出一些未正确理解的文章. 在这里,我将非常感谢. 哈哈.

使用两种类型的限定符(volatile和strict)与优化编译器之间存在一定的关系. 在变量类型定义中使用关键字volatile指示该变量的值中存在不确定因素. 换句话说,此变量不仅会被我们编写的程序更改,而且可能会被外部代理程序更改(例如: 硬件中断,外部程序等). 这样,不能保证如果程序不更改此变量的值并且有多次调用,则在寄存器中输入的值将是正确的.

从编译器优化的角度,举一个例子:

int x = 5;

int a,b;

a = x;

b = x;

因为程序没有更改X的值,但是有多个调用,为了优化运行速度,编译器将为a分配一个值,然后将X的值从内存中放入寄存器中. 当给b赋值时,不要再次在X存储器地址中读取该值,而是直接在寄存器中给b赋5. 此优化对于普通变量没有问题. 但是,如果将其定义为volatile int x;这意味着x可以由程序代码之外的其他代理更改. 如果编译器也使用此优化,则很可能在分配b的值时,x的值已被程序外部的硬件中断更改. 这样,从寄存器获得的值肯定是错误的.

因此,在将volatile关键字添加到变量时,除了表明该变量可以被其他代理更改外,还明确指出编译器无法以上述方式优化此变量: 每次调用此变量时,从变量的地址获取值,而不是从寄存器获取值(此变量使用的硬件内存地址是与并行运行的其他程序共享数据,因此,程序本身更改变量值还是其他代理更改变量值,它正在更改内存地址数据. )

看一个有趣的例子:

int方(volatile int * a)

{

return(* a * * a);

}

此函数的目的是计算平方根,但是由于指针使用volatile关键字,因此不能保证两次获得的指针地址中的值都相同,因此计算结果可能不是我们需要. 考虑更改为:

int方(volatile int * a)

{

int temp = * a;

c语言对应汇编语句_c语言与汇编语言的区别_c语言对应汇编语句

return(temp * temp);

}

restrict关键字只能用于修改指针,指示定义的指针是访问指针中数据的唯一方法. 目的是告诉编译器可以进行一些优化. 查看示例:

int x = 2;

int * a =(int *)malloc(sizeof(int));

* a = 2;

int * b =&x;

* a + = 2;

* b + = 2;

x * = 3;

* a + = 3;

* b + = 3;

在编译器进行优化时,可以使用以下语句代替: * a + = 5;这对于a是正确的,但是如果使用* b + = 5来优化b,那是不正确的. 因为其他变量会影响结果. 因此,当编译器不确定某些因素时,它将放弃寻找优化的方法. 如果在变量前添加strict关键字. 它告诉编译器放心地进行优化. 但是编译器不会验证您定义为strict的指针是否确实是访问某些数据的唯一方法. 就像数组的下标超出范围一样,如果不遵循规则,编译器将不会指出错误,但后果是您自己负责的: )

还要看一个有趣的类别:

voidchange_array(restrict int * array,const limit int * value,const int size)

{

for(int i = 0; i

{

array [i] + = * value;

}

}

int main(void)

{

int * array [SIZE] = {1,2,3};

change_array(array,&array [0],SIZE);

for(int i = 0; i

{

printf(“%d \ n”,array [i]);

}

}

如果编译器支持优化,则运行后的结果为: 2 3 4而不是实际的正确结果: 2 4 5.这表明在定义函数时两个指针受到限制,因此编译器对其进行了优化: 当程序调用该函数时,将在寄存器中生成值指针的变量值的副本. 随后的执行是获取寄存器的值. 同时,可以看出,当您不遵循由strict定义的指针定义的规则并且只能由指针修改(函数中值指针所指向的数据时,数组指针也是在调用main时进行了修改),编译器不会进行检查.

为了进行优化,必须强制使用volatile,并建议使用strict. 也就是说,添加volatile不会强制优化,而添加strict编译器可能不一定会优化. 在大多数情况下,限制的结果与不添加任何内容的结果相同. 限制仅告诉编译器可以自由进行一些优化假设. 它还告诉调用方仅使用满足limit中定义的条件的参数,如果不听话,呵呵. .

关键字limit是C99标准添加的,在C ++中不受支持,因此无法通过在VC ++中添加limit关键字进行编译: (

关于加入限制,我还在网上找到了一个短篇小说:

为了提高Cray机器的效率,ANSI C委员会提出了一种名为noalias的机制来解决此问题. 它用于解释可以将C指针视为别名,但是这种机制还不成熟. 此事件激怒了Dennis Ritchie,他对C的标准化过程进行了唯一的干预. 他写了一封公开信,说“ noalias必须站在一边,这是不能商量的. ”

后来,Cray的Mike Holly发现了这个问题,并向数值C语言扩展工作组和C ++委员会提出了改进的抗锯齿建议. 建议的想法是允许程序员通过将指针描述为“限制”来声明可以将其视为没有别名. 该提议已被C99接受,但标准的C ++拒绝了.


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-249642-2.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 姬满
      姬满

      不行了不行了我受不了新表情的诱惑了还有四天我就升级

    • 景旭
      景旭

      很好听为了你自己的梦想还有为了喜欢你的人继续努力吧加油

    • 道子与哈金
      道子与哈金

      民国百万计的伪军汉奸

    热点图片
    拼命载入中...