写入视频内存(0xB8000)和易失性指针

nac*_*yde 3 c memory pointers volatile

我正在尝试用C编写自己的小内核,实际上我想写一个print函数来显示字符串.因此,我想写入视频内存(0xB8000).

所以,我试过这样的:

unsigned char *video = (unsigned char *)0xB8000;

*video = 'A';
Run Code Online (Sandbox Code Playgroud)

这实际上有效,但以下不是:

char x = 0;
unsigned char *video = (unsigned char *)(0xB8000 + x);

*video = 'A';
Run Code Online (Sandbox Code Playgroud)

经过一些研究,我认为原因可能是编译器的优化,OSDev给我解决方案:使用volatile关键字.所以我对这个关键字做了一些研究.OSDev建议:

char x = 0;
volatile unsigned char *video = (volatile unsigned char *)(0xB8000 + x);

*video = 'A';
Run Code Online (Sandbox Code Playgroud)

这样,它应该工作.编译器假定video指针指向的值可以更改,然后不进行优化.但是,如果以后我想改变它,比如:

video = (volatile unsigned char *)(video + 2);
Run Code Online (Sandbox Code Playgroud)

我不应该将指针定义为volatile,像unsigned char * volatile video?那么编译器知道地址可以改变吗?

nem*_*oid 5

关键volatile是告诉编译器变量的内容可能会在代码执行之外发生变化或产生副作用.正如标准(C99 6.7.3.6)所说:

具有volatile限定类型的对象可能以实现未知的方式进行修改,或者具有其他未知的副作用.因此,任何涉及这种对象的表达都应严格按照抽象机的规则进行评估,如5.1.2.3所述.此外,在每个序列点,最后存储在对象中的值应与抽象机器规定的值一致,除非由前面提到的未知因素修改.什么构成对具有volatile限定类型的对象的访问是实现定义的.

这就是为什么你需要告诉编译器变量指向的内存是volatile.但是,更改指针所指向的地址不会产生任何副作用,并且在执行代码之外不会自行更改,因此指针本身没有理由是易失性的.如果我们必须标记我们希望在某些时候改变的volatile所有变量,几乎所有变量都必须标记为这样.