phoenix os在x86下vesa圖形界面的實現

phoenix圖形界面支持1600*800以下的所有分辨率,以及各種色數,包括8位色,16位色,24位色等。
首先要介紹一個概念:Linear Frame Buffer ,這個是什麼呢?這個是vesa2.0以後新增的一個概念(現在顯卡一般都支持vesa2.0及以上了),用於標誌顯存的物理地址,而我們只要往這個地址裏面寫數據就可以在顯示器上顯示出來,其餘的我們都不需要關心,神奇吧!這個數據根據顏色的位數不同可以是8位數,16位數,24位數,32位數等等。。這個數據標誌了一個RGB顏色,關於RGB顏色我就不多說了。
我們首先要做的是設置顯示模式,也就是分辨率和顏色,在nasm下這只需要3行代碼,通過BIOS 0x10中斷來實現。注意這個必須在實模式設置,進入保護模式後就無法使用0x10中斷了。
代碼如下:
  mov ax , 0x4f02
  mov bx , 0x4117       ;設置顯示模式1024 * 768 ( 5:6:5 )
  int 0x10
 
代碼很簡單,下面來解釋一下:
首先第一行,mov ax , 0x4f02,這行代碼的作用是將我們所要用的功能號存入ax,這個功能號表示我們要設置顯示模式。
第二行mov bx , 0x4117   是設置顯示模式,其中117表示顯示模式爲1024 * 768 ( 5:6:5 ),前面的4表示我們需要使用Linear Frame Buffer 。如果需要設置其他的顯示模式那麼可以參考最下面的顯示模式列表。
第三行 int 0x10 調用10號中斷,完成!現在我們的操作系統就進入了1024 * 768 ( 5:6:5 )顯示模式:),但是我們現在只是進入了這個模式,還不能顯示東西,因爲我們還沒有得到顯存的地址Linear Frame Buffer 呢~~下面我們就來看怎樣得到這個地址
首先我們通過0x10中斷讀取一個數據結構,這個數據結構十分龐大,有256個字節,我們需要用這樣一個結構體來標誌它
typedef struct _mode_info         /* VESA information for a specific mode */
{
   uint16 ModeAttributes  ;
   uint8  WinAAttributes  ;
   uint8  WinBAttributes  ;
   uint16 WinGranularity  ;
   uint16 WinSize            ;
   uint16 WinASegment         ;
   uint16 WinBSegment      ;
   uint32  WinFuncPtr           ;
   uint16 BytesPerScanLine     ;
   uint16 XResolution         ;
   uint16 YResolution          ;
   uint8  XCharSize            ;
   uint8  YCharSize            ;
   uint8  NumberOfPlanes       ;
   uint8  BitsPerPixel         ;
   uint8  NumberOfBanks        ;
   uint8  MemoryModel         ;
   uint8  BankSize    ;      
   uint8  NumberOfImagePages ;
   uint8  Reserved_page    ;   
   uint8  RedMaskSize   ; 
   uint8  RedMaskPos   ;      
   uint8  GreenMaskSize;      
   uint8  GreenMaskPos ;      
   uint8  BlueMaskSize;      
   uint8  BlueMaskPos ;        
   uint8  ReservedMaskSize ;  
   uint8  ReservedMaskPos ;    
   uint8  DirectColorModeInfo; 
   /* VBE 2.0 extensions */
   uint16  *PhysBasePtr ;      
   uint32  Reserved2 ;
   uint16  Reserved1 ; 
   /* VBE 3.0 extensions */
   uint16 LinBytesPerScanLine  ;
   uint8  BnkNumberOfPages ;   
   uint8  LinGreenMaskSize ;  
   uint8  LinGreenFieldPos ;   
   uint8  LinBlueMaskSize ;   
   uint8  LinBlueFieldPos ;    
   uint8  LinRsvdMaskSize ;   
   uint8  LinRsvdFieldPos ;   
   uint32  MaxPixelClock  ;    
   uint8  Reserved[190] ;    
}mode_info;
 
一看很眼暈是不?我當時看到也這樣,但是不用擔心,我們需要的只有一個,uint16  *PhysBasePtr,這個是什麼?這個就是我們要取得的顯存地址,呵呵,簡單吧。接下來我們來看如何取得這個數據結構,代碼也很簡單,就幾行
 mov bx , 0x9000
  mov es , bx
  mov di , 0x0
  mov ax , 0x4f01
  mov cx , 0x117
  int 0x10
 
首先是ax中的功能號0x4f02變成0x4f01了,這表示我們想取得顯示模式信息。當int 0x10調用這個功能號的時候我們要取得的模式信息數據結構會被保存到es:di的地址中,這裏我們把es賦值爲0x9000,di賦值爲0x0,這樣這個數據結構就會被存放到物理地址es:di=0x90000中。
然後cx中保存的是所要取得的顯示模式的標誌號。這裏是117,表示要取得1024 * 768 ( 5:6:5 )模式的信息。
 
簡單把,現在上面那個big數據結構就被保存在物理地址0x90000中了
現在我們想往顯存裏寫數據只需:
unsigned short  *video_base;      //聲明一個指向顯存的指針,指針指向的類型根據顏色
                                                   //位 數來決定
mode_info *p=(mode_info*)0x90000;     //然後聲明一個指向模式信息數據結構的指針p,並且
                                                                  //讓p指向我們模式信息所在的地址0x90000
 video_base=p->PhysBasePtr;                 //把模式信息中Linear Frame Buffer 地址取出來賦給
                                                                  //v ideo_bases
 
現在我們可以對顯存爲所欲爲了,呵呵
比如說畫一個點就用下面這個語句:
*video_base=0xaaa   ;
其中0xaaaa是顏色值,好像是橘紅色的:)
 
我就寫這麼多把,其餘的就靠個人發揮了,想畫什麼就直接寫顯存就可以了。
謝謝大家的支持!
附:
顯示模式表:
100h - 640x400 256 108h - 80 60
101h - 640x480 256 109h - 132 25
102h 6Ah 800x600 16 10Ah - 132 43
103h - 800x600 256 10Bh - 132 50
104h - 1024x768 16 10Ch - 132 60
105h - 1024x768 256
106h - 1280x1024 16
107h - 1280x1024 256
10Dh - 320x200 32K (1:5:5:5)
10Eh - 320x200 64K (5:6:5)
10Fh - 320x200 16.8M (8:8:8)
110h - 640x480 32K (1:5:5:5)
111h - 640x480 64K (5:6:5)
112h - 640x480 16.8M (8:8:8)
113h - 800x600 32K (1:5:5:5)
114h - 800x600 64K (5:6:5)
115h - 800x600 16.8M (8:8:8)
116h - 1024x768 32K (1:5:5:5)
117h - 1024x768 64K (5:6:5)
118h - 1024x768 16.8M (8:8:8)
119h - 1280x1024 32K (1:5:5:5)
11Ah - 1280x1024 64K (5:6:5)
11Bh - 1280x1024 16.8M (8:8:8)
81FFh Special Mode (see below for details)
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章