与DOS和BIOS函数一样,有很多内存位置也包含了计算机的一些有用和有趣的信息。你想不使用中断就知道当前显示模式吗?该信息存储在40:49H(段地址为40H,偏移量为49H)中。你想知道用户当前是否按下了Shift,Ctrl或Alt键吗?该信息存储在40:17H中。你想直接写屏吗?单色显示(Monochrome)模式的视频缓冲区起始地址为B800:O,彩色文本模式和16色图形模式(低于640×480 16色)的视频缓冲区起始地址为B8000:0,其余标准图形模式(等于或高于640×480 16色)的视频缓冲区起始地址为A000:O,详见14.8。下面的例子说明了如何把彩色文本模式的字符打印到屏幕上,注意它只是对前文中的例子做了一点小小的修改。
# include <stdlib. h>
# include <dos. h>
char GetAKey(void) ;
void OutputString(int, int, unsigned int, char * );
main (int argc, char * * argv)
{
char str[l28];
union REGS regs;
int ch, tmp;
/* copy argument string; if none, use "Hello World" */
strcpy(str, (argv[1] == NULL ? "Hello World" : argv[1]));
/* print the string in red at top of screen */
for(tmp = 0;((ch = GetAKeyO) ! = 27); tmp+=strlen(str)) {
outputString(0, tmp, 0x400,str);
}
}
char
GetAKey()
{
union REGS regs;
regs. h. ah = 0; /* get character */
int86(0xl6, ®s, ®s);
return((char)regs. h. al);
}
void
OutputString(int row, int col, unsigned int video Attribute, char * outStr)
{
unsigned short far * videoPtr;
videoPtr= (unsigned short far * ) (0xB800L <<16);
videoPtr + = (row * 80) + col; /* Move videoPtr to cursor position */
videlAttribute & = 0xFF00; /* Ensure integrity of attribute */
/* print string to RAM */
while ( * outStr ! = '\0'){
/* If newline was sent, move pointer to next line, column 0 */
if( (* outStr == '\n') || (*outStr == 'V') ){
videoPtr + = (80- (((int)FP-OFF(videoPtr)/2) % 80));
outStr+ + ;
continue;
}
/* If backspace was requested, go back one */
if( *outStr = = 8){
videoPtr -- ;
outStr++ ;
continue;
}
/* If BELL was requested, don't beep, just print a blank and go on */
if ( * outStr = = 7) {
videoPtr+ + ;
outStr++ ;
continue ;
}
/* If TAB was requested, give it eight spaces */
if ( * outStr == 9){
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
* videoPtr++ = video Attribute | ' ' ;
outStr+ + ;
continue;
}
/* If it was a regular character, print it */
* videoPtr = videoAttribute | (unsigned char) * outStr;
videoPtr+ + ;
outStr + + ;
}
return;
}
显然,当你自己来完成把文本字符打印到屏幕上这项工作时,它是有些复杂的。笔者甚至已经对上例做了一些简化,即忽略了BELL字符和一些其它特殊字符的含义(但笔者还是实现了回车符和换行符)。不管怎样,这个程序所完成的任务与前文中的例子基本上是相同的,只不过现在打印时你要控制字符的颜色和位置。这个程序是从屏幕的顶端开始打印的。如果你想看更多的使用内存位置的例子,可以阅读20.12和20.17——其中的例子都使用了指向DOS内存的指针来查找关于计算机的一些有用信息。
正在执行重要的代码时,把这一情况通知DOS。然而,该标志对程序员也是很有用的,因为他们能由此知道什么时候DOS处于忙状态。尽管从DOS 2.0版开始就有这个函数了,但因为Microsoft最近已经公开了这个函数,所以从技术角度上讲它已不再是一个未公开的函数。有几本很不错的书介绍了已公开和未公开的DOS函数,对这个问题有兴趣的读者可以去阅读这些书。