图形显示[ExpOS]开发经验(2)保护模式中不依赖bios

导读:
  保护模式中不依赖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() */
  pokeb(0xB800, 0, '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 /* _farpokeb() */
  #include /* _dos_ds */
  _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() */
  movedata(0xB800, 80 * 2,
  0xB800, 0,
  80 * (25 - 1) * 2);
  DJGPP 代码 scroll 80x25 display up one line (color emulation):
  #include /* movedata() */
  #include /* _dos_ds */
  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 crtc_adr = 0x3D4; /* 0x3B4 for monochrome */
  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 /* outportb() */
  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 /* atoi() */
  #include /* printf() */
  //#include "../port.c" /* inportb(), peekw() */
  /********************************* TURBO C **********************************/
  #if defined(__TURBOC__)
  #include /* inportb(), peek() */
  #define peekw(S,O) peek(S,O)
  /********************************* DJGPP ************************************/
  #elif defined(__DJGPP__)
  #include /* _CRT0_FLAG_LOCK_MEMORY */
  #include /* inportb() */
  //#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 /* __djgpp_conventional_base, __djgpp_nearptr_enable() */
  #include /* printf() */
  #include /* _CRT0_FLAG_NEARPTR, _crt0_startup_flags */
  #define peekw(S,O) *(unsigned short *)(16uL * (S) + (O) + /
  __djgpp_conventional_base)
  /* far pointers */
  #else
  #include /* _farpeekw() */
  #include /* _dos_ds */
  #define peekw(S,O) _farpeekw(_dos_ds, 16uL * (S) + (O))
  #endif
  /******************************** WATCOM C **********************************/
  #elif defined(__WATCOMC__)
  #include /* inp() */
  #if defined(__386__)
  /* CauseWay DOS extender only */
  #define peekw(S,O) *(unsigned short *)(16uL * (S) + (O))
  #else
  #include /* MK_FP() */
  #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, 2, 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

你可能感兴趣的:(操作系统)