C 写入视频存储器(0xB8000)&;易变指针

C 写入视频存储器(0xB8000)&;易变指针,c,pointers,memory,volatile,C,Pointers,Memory,Volatile,我正试图用C编写自己的小内核,实际上我想编写一个打印函数来显示字符串。因此,我想写入视频内存(在0xB8000) 所以,我试着这样: unsigned char *video = (unsigned char *)0xB8000; *video = 'A'; 这实际上是可行的,但以下情况不可行: char x = 0; unsigned char *video = (unsigned char *)(0xB8000 + x); *video = 'A'; 经过一些研究,我发现原因可能是编

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

所以,我试着这样:

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

*video = 'A';
这实际上是可行的,但以下情况不可行:

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

*video = 'A';
经过一些研究,我发现原因可能是编译器的优化,并给出了解决方案:使用
volatile
关键字。所以我对这个关键词做了一些研究。OSDev建议:

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

*video = 'A';
这样,它应该会起作用。编译器假定
video
指针指向的值可以更改,然后不对其进行优化。但是,如果以后我想改变它,比如:

video = (volatile unsigned char *)(video + 2);
我是否应该将指针定义为
volatile
,比如
unsigned char*volatile video
?因此编译器知道地址可以更改?

为什么不可以:

unsigned char * video = 0xB8000;
video[x] = 'A';

volatile
的要点是告诉编译器变量的内容可能会更改或在代码执行之外产生副作用。正如(C99 6.7.3.6)所述:

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


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

当然,这是可能的,也许是最好的方法,但这并不能向我解释我的volatile问题背后的原因;)这不管用。编译器可能会对其进行优化。铸造地址文字是betterI不明白没有volatile什么是不起作用的<代码>无符号字符*视频=(无符号字符*)(0xB8000+x)。我想问题是
x
char
而不是
int/unsigned
。类型可能是问题所在,而不是非问题所在-volatility@i486如果编译器能够推断出
视频
的内容从未被读取,它可能会优化对它的写入。为什么
(unsigned char*)(0xB8000+x)
不会将值写入视频内存,而
(unsigned char*)0xB8000
会这样做?我认为不可能有这样的优化。只有
video
的值可以保存在CPU寄存器中,而不是它的内存位置。我同意这很奇怪,但优化在第一种情况下不会发生的事实并不是说它在第二种情况下不会发生。请注意,
volatile
在这里的使用(可能)是有效的,在整个内核中使用它之前,应该先阅读。一个更好的方法,而不是声明
视频
易失性
,是将所有需要易失性的访问强制转换为
易失性