volatile

【转贴】GCC 内联汇编

坚强是说给别人听的谎言 提交于 2020-01-05 09:56:10
1. 简介 1.1 版权许可 Copyright (C) 2003 Sandeep S. 本文档自由共享;你可以重新发布它,并且/或者在遵循自由软件基金会发布的 GNU 通用公共许可证下修改它;也可以是该许可证的版本 2 或者(按照你的需求)更晚的版本。 发布这篇文档是希望它能够帮助别人,但是没有任何担保;甚至不包括可售性和适用于任何特定目的的担保。关于更详细的信息,可以查看 GNU 通用许可证。 1.2 反馈校正 请将反馈和批评一起提交给 Sandeep.S。我将感谢任何一个指出本文档中错误和不准确之处的人;一被告知,我会马上改正它们。 1.3 致谢 我对提供如此棒的特性的 GNU 人们表示真诚的感谢。感谢 Mr.Pramode C E 所做的所有帮助。感谢在 Govt Engineering College 和 Trichur 的朋友们的精神支持和合作,尤其是 Nisha Kurur 和 Sakeeb S 。 感谢在 Gvot Engineering College 和 Trichur 的老师们的合作。 另外,感谢 Phillip , Brennan Underwood 和 colin@nyx.net ;这里的许多东西都厚颜地直接取自他们的工作成果。 2. 概览 在这里,我们将学习 GCC 内联汇编。这里内联表示的是什么呢?

volatile限定符

眉间皱痕 提交于 2020-01-05 06:31:31
volatile关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素更改,比如:操作系统、硬件或者其它线程等。由于访问寄存器的速度要快过RAM,所以编译器一般都会作减少存取外部RAM的优化。遇到这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。 volatile的本意是“易变的”,不过翻译成“直接存取原始内存地址”更为合适。“易变”是因为外在因素引起的,象多线程,中断等,并不是因为用volatile修饰了的变量就是“易变”了,假如没有外因,即使用volatile定义,它也不会变化。 一个参数 可以既是const又是volatile, 它是volatile因为它可能被意想不到地改变。它是const因为程序不应该试图去修改它。 对于这样的代码: volatile int i = 10; int a = i; ... //其他代码,并未明确告诉编译器,对i进行过操作 int b = i; volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从内存中i的地址读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来

volatile的作用

孤街醉人 提交于 2020-01-05 06:26:43
一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2). 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) 3). 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。嵌入式系统程序员经常同硬件、中断、RTOS等等打交道,所用这些都要求volatile变量。不懂得volatile内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑这否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。 1). 一个参数既可以是const还可以是volatile吗?解释为什么。 2). 一个指针可以是volatile 吗?解释为什么。 3). 下面的函数有什么错误: int square(volatile int *ptr) { return *ptr * *ptr; } 下面是答案: 1). 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改变

java: using volatile at one variable VS each variable

倾然丶 夕夏残阳落幕 提交于 2020-01-05 04:57:18
问题 the following problem: volatile Object A; volatile Object B; volatile Object C; Thread1: reads and writes to A-C Thread2: the same as Thread1 So my question is: would it better if i do something like this: Object A; Object B; Object C; volatile boolean memoryBarrier=true; Thread1: Before read of A-C: read memoryBarrier After some write of A-C: write memoryBarrier=true; Thread2: the same as Thread1: Before read of A-C: read memoryBarrier After some write of A-C: write memoryBarrier=true; Is

volatile关键字

和自甴很熟 提交于 2020-01-05 04:51:44
  volatile是c语言的修饰符。一个定义为volatile的变量是指这变量会被意想不到地改变,这样,编译器就不会去假设该变量的值。 编译器什么时候会假设变量的值?当读取一个变量时,为提高读取速度,编译器优化时有时会把变量的值读取到一个寄存器中;以后再 取该变量的值时,就直接从寄存器中取值。 volatile声明的变量却不会这样,而是每次都存取原始内存地址。   (在嵌入式开发中,同硬件、中断、RTOS等打交道时都需要使用volatile变量) 遇到volatile关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问。 #include <stdio.h> int main(int argc, char* argv[]) { int x = 100; int a = x; printf("x = %d\n", a); //汇编语句中改变内存中x的值,但编译器并不知道 __asm { mov dword ptr[ebp - 4], 10h } int b = x; printf("x = %d\n", b); getchar(); return 0; } 上面代码,在debug版本(无优化)中输出为: x=100 x=16 在release版本(有优化)中输出为: x=100 x=100 这表示在release版本下,编译器对代码进行了优化

C语言中的volatile

痴心易碎 提交于 2020-01-05 04:49:47
1.volatile有什么含义?有什么用法? 官方定义是: 一个变量也许会被后台程序改变。 关键字volatile与const绝对独立。它指示一个变量也许会被某种方式修改,这种方式按照正常程序流程分析是无法预知的(例如,一个变量也许会被一个中断服务程序所修改)。这个关键字使用以下语法定义: volatile data-defiinition; 注:变量如果加了voletile修饰,则会从内存中重新装载内容,而不是直接从寄存器中拷贝内容。 2.编译器的优化 在本次线程内,当读取一个变量时,为了提高读取速度,编译器进行优化时有时会先把变量读取到一个寄存器中;以后,再读取变量值时,就直接从寄存器中读取;当变量值在本线程里改变时,会同时把变量的新值copy到该寄存器中,以保持一致。 当变量因别的线程值发生改变,上面寄存器的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致。 3.常见的问题 (1)说明关键字volatile有什么含意,并给出例子。 volatile表示被修饰的符号是易变的。告诉编译器不要随便优化我的代码!! *一个硬件寄存器 *中断中用到的变量 *线程之间共享变量 volatile int a = 10; while((a & 0x01) == 0); #define P_UART_STATUS ((const volatile unsigned int *

C中的volatile用法

可紊 提交于 2020-01-05 04:47:36
volatile 影响编译器编译的结果,指出,volatile 变量是随时可能发生变化的,与volatile变量有关的运算,不要进行编译优化,以免出错,(VC++ 在产生release版可执行码时会进行编译优化,加volatile关键字的变量有关的运算,将不进行编译优化。)。 例如: volatile int i=10; int j = i; ... int k = i; volatile 告诉编译器i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的可执行码会重新从i的地址读取数据放在k中。 而 优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在k中。而不是重新从i里面读。这样以来,如果 i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问,不会出错。 /********************** 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: 1) 并行设备的硬件寄存器(如:状态寄存器) 2) 一个中断服务子程序中会访问到的非自动变量(Non

volatile用法

做~自己de王妃 提交于 2020-01-05 04:41:08
volatile 用法 关键字 volatile 是 Java 提供的最轻量级的同步机制, Java 内存模型对 volatile 专门定义了一些特殊的访问规则。下面我们就看它的规则: 当一个变量被 volatile 修饰后,它将具备以下两种特性。 1.线程可见性:当一个线程修改了被 volatile 修饰的变量后,无论是否加锁,其他线程都可以立即看到最新的修改,而普通变量做不到这点。 2.禁止指令重排序优化,普通的变量仅仅保证在该方法的执行过程中所有依赖赋值结果的地方能获取正确的结果,而不能保证变量赋值操作的顺序和程序代码的执行顺序一致。(数据重排请参加: http://www.infoq.com/cn/articles/java-memory-model-2 ) 一些人认为使用 volatile 可以替代传统锁,提升并发性能,这个认识是错误的。 Volatile 仅仅解决了可见性的问题,但是他并不能保证互斥性,也就是说多线程并发修改某个变量时,依旧会产生多线程问题。因此,不能靠 volatile 来完全替代传统的锁。 Volatile 最适合使用的是一个线程写、其他线程读的场合,如果有多个线程并发写操作,仍然需要使用锁或者线程安全的容器或者院子变量来替代。对一个 volatile 变量的读,总是能看到(任意线程)对这个 volatile 变量最后的写入。 来源: https:/

01.Volatile相关知识

﹥>﹥吖頭↗ 提交于 2020-01-05 04:36:41
1.Volatile相关知识 Volatile是区分C程序员和嵌入式系统程序员最基本的问题。 嵌入式系统程序员经常同硬件、中断、RTOS等打交道,所有这些都要求volatile变量。不懂volatile很可能会带来灾难。 volatile的作用 作为指令关键字, 确保本条指令不会因编译器的优化而省略,要求每次直接读值.非常典型的就是寄存器的值可能被人为的从硬件上改变,所以必须要求每次直接读值。 简单地说就是防止编译器对代码进行优化 ,比如程序: XBYTE[2]=0x55; XBYTE[2]=0x56; XBYTE[2]=0x57; XBYTE[2]=0x58; 如果对外部硬件的上述四条语句分别表示不同的操作, 会产生四种不同的动作,那么编译器就不能像对待纯粹的程序那样对上述四条语句进行优化只认为XBYTE[2]=0x58,而忽略前三条语句,并且只产生1条机器码。如果XBYTE用volatile修饰过,此时编译器会逐一的进行编译并产生相应的4条机器码。 再详细解释一下:定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。 下面是volatile变量的几个例子: 1). 并行设备的硬件寄存器(如:状态寄存器) 2).

c 语言 volatile 关键字

∥☆過路亽.° 提交于 2020-01-05 04:15:16
一.前言 1.编译器优化介绍: 由于内存访问速度远不及CPU处理速度,为提高机器整体性能,在硬件上引入硬件高速缓存Cache,加速对内存的访问。另外在现代CPU中指令的执行并不一定严格按照顺序执行,没有相关性的指令可以乱序执行,以充分利用CPU的指令流水线,提高执行速度。以上是硬件级别的优化。再看软件一级的优化:一种是在编写代码时由程序员优化,另一种是由编译器进行优化。编译器优化常用的方法有:将内存变量缓存到寄存器;调整指令顺序充分利用CPU指令流水线,常见的是重新排序读写指令。对常规内存进行优化的时候,这些优化是透明的,而且效率很好。由编译器优化或者硬件重新排序引起的问题的解决办法是在从硬件(或者其他处理器)的角度看必须以特定顺序执行的操作之间设置内存屏障(memory barrier), Linux 提供了一个宏解决编译器的执行顺序问题。 void Barrier(void) 这个函数通知编译器插入一个内存屏障,但对硬件无效,编译后的代码会把当前CPU寄存器中的所有修改过的数值存入内存,需要这些数据的时候再重新从内存中读出。 2.volatile总是与优化有关,编译器有一种技术叫做数据流分析,分析程序中的变量在哪里赋值、在哪里使用、在哪里失效,分析结果可以用于常量合并,常量传播等优化,进一步可以消除一些代码。但有时这些优化不是程序所需要的