图形显示[ExpOS]开发经验(2)保护模式中不依赖bios
发布时间:2020-12-13 20:35:54 所属栏目:百科 来源:网络整理
导读:导读: 保护模式中不依赖bios才是重点. 原理: 显示到屏幕上的字母和符号统统存在于一段叫做 framebuffer 的显存中. 至于其出现于内存的物理地址,要看VGA板的工作模式. VGA 的两种模式是: monochrome (单色?) emulation,或者color emulation. emulation---|--f
导读:
保护模式中不依赖bios才是重点. 原理: 显示到屏幕上的字母和符号统统存在于一段叫做 framebuffer 的显存中. 至于其出现于内存的物理地址,要看VGA板的工作模式. VGA 的两种模式是: monochrome (单色?) emulation,或者color emulation. emulation---|--framebuffer linear address--|--framebuffer real-mode address--|--I/O address of CRTC color-------|--B8000h----------------------|--B800h:0000 --------------------|--3D4h monochrome--|--B0000h----------------------|--B000h:0000 --------------------|--3B4h CRTC 是VGA的一个功能单元,待会再讨论有关CRTC的东东. 一般来说,应该是 color emulation,记得大一的时候我们的实验室倒是有几台386 上有 monochrome 的古董. 备注1 的c代码可以检测VGA是处于那种工作模式. 如果能够看懂,拿来用用应该不成问题. 不会弄代码的格式,大家拷贝后自己整理吧. 这里给一个简单的. /* video card mono/colour detection by Dark Fiber * returns 0=mono,1=colour */ int detect_video_type(void) { int rc; char c=(*(USHORT*)0x410&0x30 /* C can be 0x00 or 0x20 for colour,0x30 for mono if(c==0x30) rc=0; // mono else rc=1; // colour return rc; } 字符及属性 在framebuffer中的每个字符都占用两个字节: ASCII 码值在地址 N 的话,N+1 就是他的属性字节. 属性字节的各个位的含义如下. b7 ----- 闪烁 b6:b4 -- 背景色(0-7) b3:b0 -- 前景色(0-15) color value -- color -- color value -- color 0 ------------ 黑色------ 8 ---------- 暗灰 1 ------------ 蓝色------ 9 ---------- 亮蓝 2 ------------ green ---- 10 --------- bright green 3 ------------ cyan ----- 11 --------- bright cyan 4 ------------ red ------ 12 --------- pink 5 ------------ magenta -- 13 --------- bright magenta 6 ------------ brown ---- 14 --------- yellow 7 ------------ white ---- 15 --------- bright white 假定使用color模式: Turbo C 代码的例子(cpu 工作于 16-bit real mode),把白色的 'H' 以蓝色背景放到屏幕左上角. #include pokeb(0xB800,'H'); pokeb(0xB800,1,0x1F); NASM 汇编中这么写(16-bit real mode): mov bx,0B800h mov es,bx mov byte [es:0],'H' mov byte [es:1],1Fh DJGPP 代码(32-bit pmode),有所不同. 把黄的 'H' 以红色背景放到屏幕右上角.因为处于保护模式,我们使用far指针. #include #include _farpokeb(_dos_ds,0xB8000 + 79 * 2 + 0,'*'); _farpokeb(_dos_ds,0xB8000 + 79 * 2 + 1,0x4E); 非得用 near 指针? #include #include #include unsigned char *fb; if(!(_crt0_startup_flags &_CRT0_FLAG_NEARPTR)) { if(!__djgpp_nearptr_enable()) { printf("Could not enable nearptr access/n"); return -1; } } /* probably Windows NT DOS box */ fb = (unsigned char *)0xB8000 + __djgpp_conventional_base; fb[79 * 2 + 0] = '*'; fb[79 * 2 + 1] = 0x4E; Scrolling(滚屏) BIOS 滚屏就算了吧?! 如果使用 movedata(),也算简单. 与memcpy() 不同的地方在于movedata对于源和目的都使用 far指针. Turbo C 代码: 在 80x25 的方式下上滚一行(color emulation): #include movedata(0xB800,80 * 2, 0xB800, 80 * (25 - 1) * 2); DJGPP 代码 scroll 80x25 display up one line (color emulation): #include #include movedata(_dos_ds,0xB8000L + 80 * 2, _dos_ds,0xB8000L, 80 * (25 - 1) * 2); 使用 movedata() 的的话,如果 src hardware scrolling 硬件来做滚动就比较快了. 把VGA配置成使用不同地址的framebuffer 就可以实现快速滚屏. CRTC 寄存器 12 号13号 分别包含framebuffer 相对于B0000h,B8000h,or A0000h 之偏移(offset) 的MSB 与 LSB . /* scroll up one line */ #include unsigned short offset = 80; /* the CRTC index is at crtc_adr + 0 select register 12 */ outportb(crtc_adr + 0,12); /* the selected CRTC register appears at crtc_adr + 1 */ outportb(crtc_adr + 1,offset >>8); outportb(crtc_adr + 0,13); outportb(crtc_adr + 1,offset &0xFF); 硬件滚屏的缺陷在于不能够持续无限的滚动. 因为最终 framebuffer 会超过 video memory 的上(下)限. 可以用作 framebuffer 的那段内存可以分成几个虚拟控制台(virtual consoles (VCs)). 32K 的 video memory 可以被分成8 个80x25的VCs. console 译作控制台我认为不妥,这里的console无非就是虚拟的几个屏幕.上面的代码就可以选择把那个虚拟屏呈现给用户. (Linux 的 VCs 使用了不同的管理方法,我不知道.) Moving the cursor CRTC 寄存器14号和 15 号,包含光标位置的 MSB LSB . 光标的位置用相对B8000h 或 B0000h的偏移来表示. #include unsigned short crtc_adr = 0x3D4; /* 0x3B4 for monochrome */ unsigned short offset; unsigned short x = 20,y = 3; offset = x + y * 80; /* 80 characters per line */ outportb(crtc_adr + 0,14); /* MSB of offset to CRTC reg 14 */ outportb(crtc_adr + 1,offset >>8); outportb(crtc_adr + 0,15); /* LSB of offset to CRTC reg 15 */ outportb(crtc_adr + 1,offset); [i] 不要告诉我,你不知道outportb 那里去找! [/i] 推荐网站 pc-hardware VGADOC 一个vag包 execpc的控制台代码 备注1 /***************************************************************************** Determines if VGA board is set for monochrome or color emulation. Uses 3 different algorithms. This code is public domain (no copyright). You can do whatever you want with it. *****************************************************************************/ #include #include //#include "../port.c" /* inportb(),peekw() */ /********************************* TURBO C **********************************/ #if defined(__TURBOC__) #include #define peekw(S,O) peek(S,O) /********************************* DJGPP ************************************/ #elif defined(__DJGPP__) #include #include //#define NEARPTR 1 /* near pointers; not supported in Windows NT/2k/XP DOS box Must call __djgpp_nearptr_enable() before using these functions */ #if defined(NEARPTR) #include #include #include #define peekw(S,O) *(unsigned short *)(16uL * (S) + (O) + / __djgpp_conventional_base) /* far pointers */ #else #include #include #define peekw(S,O) _farpeekw(_dos_ds,16uL * (S) + (O)) #endif /******************************** WATCOM C **********************************/ #elif defined(__WATCOMC__) #include #if defined(__386__) /* CauseWay DOS extender only */ #define peekw(S,O) *(unsigned short *)(16uL * (S) + (O)) #else #include #define peekw(S,O) *(unsigned short far *)MK_FP(S,O) #endif #define inportb(P) inp(P) #else #error Not Turbo C,not DJGPP,not Watcom C. Sorry. #endif static unsigned short g_crtc_base_adr; /***************************************************************************** Pentium 486 Bochs method color color (color) mono ------ ------- ----- ------- ------- 1 pass pass pass UNTESTED 2 pass pass pass UNTESTED 3 pass pass pass UNTESTED *****************************************************************************/ int main(int arg_c,char *arg_v[]) { int method; #if defined(__DJGPP__)&&defined(NEARPTR) if(!(_crt0_startup_flags &_CRT0_FLAG_NEARPTR)) { if(!__djgpp_nearptr_enable()) { printf("Could not enable nearptr access " "(Windows NT/2k/XP?)/nUn-define NEARPTR " "in source code and re-compile/n"); return 1; } } #endif if(arg_c <2) { printf("attempt to detect monochrome/color VGA emulation " "using one of three methods/n" "specify 1,2,or 3 on the command line/n"); return 1; } method = atoi(arg_v[1]); switch(method) { case 1: /* this method cobbled from info in Finn Thoegersen's VGADOC4 */ #define VGA_MISC_READ 0x3CC if((inportb(VGA_MISC_READ) &0x01) == 0) g_crtc_base_adr = 0x3B4; /* mono */ else g_crtc_base_adr = 0x3D4; /* color */ break; case 2: /* I forgot where this came from: "The word at low memory address 0040:0063 (or 0000:0463) contains the I/O address of the CRTC which can be used to determine whether the video system is colour or monochrome. A value of 3B4 hex indicates monochrome." (I presume 3D4 hex means color; my Pentium system has that value at 0463.) */ g_crtc_base_adr = peekw(0x40,0x63); break; case 3: /* Dark Fiber's method,from the OS FAQ [url=www.mega-tokyo.com/os]http://www.mega-tokyo.com/os[/url] from MEMORY.LST of Ralf Brown's Interrupt List 0040:0010 is Installed Hardware word,b5:b4 indicate video hardware: 00 EGA,VGA,PGA,or other with on-board video BIOS 01 40x25 CGA color 10 80x25 CGA color 11 80x25 mono text whoa,this won't work with DJGPP -- OK,I will make a slight change here if((*(unsigned short *)0x410 &30) == 0x30) */ if((peekw(0x40,0x10) &30) == 0x30) g_crtc_base_adr = 0x3B4; /* mono */ else g_crtc_base_adr = 0x3D4; /* color */ break; default: printf("didn't find 1,or 3 on the command line,sorry/n"); return 1; } /* what've we got? */ if(g_crtc_base_adr <0x3C0) printf("MONOCHROME emulation detected/n"); else printf("color emulation detected/n"); return 0; } 本文转自 http://www.cnblogs.com/huqingyu/archive/2005/02/17/105365.html (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |