我对C语言非常陌生,它是我学习Java之后接触的第二种高级编程语言。我已经掌握了大部分基础知识,但由于某种原因,我无法将单个字符写入屏幕内存。
这个程序使用Turbo C编译,在一个Am486-DX4-100处理器上运行,主频为120mhz。图形卡是一张标准的VLB Diamond Multimedia Stealth SE,使用Trio32芯片。
我的操作系统是PC-DOS 2000,并加载了ISO代码页。我在标准的MDA/CGA/EGA/VGA样式80列文本模式下运行,支持彩色。
以下是我编写的程序:
#include <stdio.h>
int main(void) {
unsigned short int *Video = (unsigned short int *)0xB8000;
*Video = 0x0402;
getchar();
return 0;
}
正如我所说,我对C语言非常陌生,所以如果我的错误看起来很明显,我很抱歉,我无法找到一个可靠的来源来让我能够理解如何做这个操作。
据我所知,在x86平台上的实模式下,文本模式下的屏幕内存从0xB8000开始。每个字符都存储在两个字节中,一个用于字符本身,另一个用于背景/前景色。想法是将值0x0402(应该是一个红色微笑的脸)写入0xB8000。这应该将其放置在屏幕左上角。
我已经考虑到了屏幕可能正在滚动的可能性,因此在执行时立即将我的字符移除的两种方法。为了解决这个问题,我尝试过:
- 使用循环重复写入此值
- 将它写得稍微向下一点。
我可以读取并打印我写入内存的值,所以它显然仍然在内存中的某个位置,但出现在屏幕上的展示效果不正确。很显然我在做错了什么,但我不知道可能会出现什么问题。如果需要任何其他细节,请告诉我。感谢您能提供的任何可能的帮助。
ds
),将0xB8000
转换为指针将截断为16位,并相对于ds
给出0x8000
的偏移量。 简而言之,实模式分段与C指针之间的映射不太容易。请注意,这不会很容易,特别是如果您不了解C和x86-16汇编语言。 - Peter Cordes0xB8000
是20位宽的。(每个十六进制数字编码四位,共有五个数字。)unsigned short int
的宽度仅为16位。在大多数bcc内存模型中,接近指针(我认为不同于huge,但已经过去几十年了。)也是16位。因此,您导致了溢出和环绕。我怀疑你最终写入了地址DS:8000
。 - Davisloruint16_t*
在x86上可能会导致段错误,但x86可以进行未对齐的加载?自动向量化以有趣的方式打破了这个“偶然有效”的代码。 - Peter Cordes