2012年6月27日 星期三

在保護模式下, 不使用 vga bios 呼叫, 將顯示卡設定為繪圖模式 (1)

這次終於成功了, 真是辛苦, 不過只有在 bochs 和 qemu 中測試成功, 以過去的經驗來說, 沒有在真實機器上測試過, 都還有失敗的風險。 

隔了半年多的時間, 如今解決這問題, 真是痛快。

根據 ref 1 改寫成 gas at&t 的版本, 在進入保護模式後, 不經由 bios call 來切換到 vga 繪圖模式, 直接讀寫 vga register。

之前有改過一個 C 語言的版本, 不過有些問題, 無法正常畫出畫面, 所以改用這版本的組合語言, 先用 tasm 測試過是正確的程式碼才進行改寫。

右圖是在真實機器 eeepc 上測試的結果 (透過軟碟片), 在真實模式下測試, 保護模式因為有些問題 (kernel loader 無法正常載入 p_kernel.elf, fixed the issue 20120703), 所以只在模擬器環境下測試。有一點會失敗的風險, 不過成功機率應該很大。

賀!這是在真實機器上的測試版本: http://descent-incoming.blogspot.tw/2012/06/vga-biso-3.html

在保護模式定址的部份稍微有點改寫, 因為和真實模式的定址方式不同, 其他大概就都是 tasm 與 gas at&t 語法的轉換, 經過這一年來的磨練, 我已經對 at&t 語法有了一點熟悉度, 改起來已經不像第一次那麼痛苦了。

 74 #MOV $0xA000, %ax
 75 MOV $0x10, %ax
 76 MOV %AX, %es
 77 #XOR %DI,%DI
 78 mov $0xa0000,%edi
 79 MOV $7000, %cx
 

將 0x10 selector (可讀寫 4GB 的記憶體範圍) 指定給 %es, 直接讀寫 0xa0000 這塊繪圖模式的位址。
 
目前還不了解程式內容, 先求能動再來看懂程式碼。進入繪圖模式後就可以好好的來練習 GUI 程式的設計, 沒有 library, bios 幫我完成的黑箱程式碼, 完全靠自己的程式那種感覺真好, 雖然是小到不行的程式, 但那種真實感真的很實在。

set_mode_p.S
  1 # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/MAIN.ASM
  2 # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/USAGE.TXT
  3 # ref: http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/README.TXT
  4 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  5 #=-   Currently supported Video Modes:    -= Mode Number =-
  6 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  7 #=-  03H    -=- 320 x 200 x 256           -=     03H     =-
  8 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  9 #=-  10H    -=- 640 x 350 x 16            -=     10H     =-
 10 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 11 #=-  12H    -=- 640 x 480 x 16            -=     12H     =-
 12 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 13 #=-  13H    -=- 320 x 200 x 256           -=     13H     =-
 14 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 15 #=- Chain 4 -=- unchained 320 x 200 x 256 -=     14H     =-
 16 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 17 #=- Mode X  -=- unchained 320 x 240 x 256 -=     15H     =-
 18 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 19 #=- Mode A  -=- unchained 320 x 400 x 256 -=     16H     =-
 20 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 21 #=- Mode B  -=- unchained 360 x 480 x 256 -=     17H     =-
 22 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 23 #=- Mode C  -=- 640 x 400 x 16            -=     18H     =-
 24 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
 25 
 26 .equ ATTRCON_ADDR      ,       0x03C0
 27 .equ MISC_ADDR         ,       0x03C2
 28 .equ VGAENABLE_ADDR    ,       0x03C3
 29 .equ SEQ_ADDR          ,       0x03C4
 30 .equ GRACON_ADDR       ,       0x03CE
 31 .equ CRTC_ADDR         ,       0x03D4
 32 .equ STATUS_ADDR       ,       0x03DA
 33 
 34 
 35 .code32
 36 #.code16
 37 .text
 38 .global switch_vga_mode
 39 switch_vga_mode:
 40 #if 0
 41 #MOV $MODE12H, %si
 42 xchg %bx, %bx #bochs magic break point
 43 mov %cs, %ax
 44 mov %ax, %ds
 45 mov %ax, %es
 46 mov %ax, %ss
 47 #endif
 48 MOV $MODE10H, %si
 49 CALL SETMODE
 50 xchg %bx, %bx #bochs magic break point
 51 call SET_OUT
 52 xchg %bx, %bx #bochs magic break point
 53 # draw screen
 54    pushw $12
 55 xchg %bx, %bx #bochs magic break point
 56    CALL CLEAR10H
 57 
 58 # Set Mode 03h
 59 #SET03H:
 60 #  MOV $MODE03H, %si
 61 #  CALL SETMODE
 62   # Must do this to ensure proper text
 63 #  CALL SETFONT
 64 #  JMP SET_OUT
 65 
 66 
 67   jmp .
 68 
 69 
 70 CLEAR10H:
 71    PUSH %BP
 72    MOV %SP, %bp
 73 
 74 #MOV $0xA000, %ax
 75 MOV $0x10, %ax
 76 MOV %AX, %es
 77 #XOR %DI,%DI
 78 mov $0xa0000,%edi
 79 MOV $7000, %cx
 80 
 81 CLEAR_LOOP2:
 82    MOV $0x03CE, %dx
 83    MOV $0x0FF08, %ax
 84    OUT %AX, %dx
 85 
 86    MOV $0, %eax
 87    #XCHG DWORD PTR ES:[DI],EAX
 88    xchgl %EAX, %es:(%edi)
 89 
 90    MOV $0x03C4, %dx
 91    #MOV AH,BYTE PTR [BP+4]
 92    #movb 4(%BP), %ah
 93    movb $0xb, %ah # 0xb is color
 94    MOV $2, %AL
 95    OUT %AX, %dx
 96 
 97    #MOV DWORD PTR ES:[DI],0FFFFFFFFH
 98    movl $0xFFFFFFFF, %es:(%edi)
 99 
100    MOV $0x0F02, %ax
101    OUT %AX, %dx
102 
103    MOV $0x03CE, %dx
104    MOV $0x0FF08, %ax
105    OUT %AX, %dx
106 
107    ADD $4, %edi
108    LOOP CLEAR_LOOP2
109 
110    POP %BP
111    RET 
112 
113 
114 
115 
116 SETMODE:
117    # Send MISC regs
118    MOV $MISC_ADDR, %dx
119    MOV (%si), %AL
120    OUT %al, %DX
121    call iodelay
122    INC %SI
123 
124    MOV $STATUS_ADDR, %dx
125    MOV (%si), %AL
126    OUT %AL, %dx
127    call iodelay
128    INC %SI
129 
130    # Send SEQ regs
131    MOV $0, %CX
132 REG_LOOP:
133    MOV $SEQ_ADDR, %dx
134    MOV %CL, %al
135    OUT %AL, %dx
136    call iodelay
137 
138    MOV $SEQ_ADDR, %dx
139    INC %DX
140    MOV (%si), %AL
141    OUT %AL, %dx
142    call iodelay
143    INC %SI
144    INC %CX
145    CMP $5, %cl
146    JL REG_LOOP
147 
148    # Clear Protection bits
149    MOV $0x0E, %ah
150    MOV 0x11, %al
151    AND 0x7F, %ah
152    MOV $CRTC_ADDR, %dx
153    OUT %AX, %dx
154    call iodelay
155 
156    # Send CRTC regs
157    MOV $0, %cx
158 REG_LOOP2:
159    MOV $CRTC_ADDR, %dx
160    MOV %CL, %al
161    OUT %AL, %dx
162    call iodelay
163 
164    MOV $CRTC_ADDR, %dx
165    INC %DX
166    MOV (%si), %AL
167    OUT %AL, %dx
168    call iodelay
169 
170    INC %SI
171    INC %CX
172    CMP $25, %CL
173    JL REG_LOOP2
174 
175    # Send GRAPHICS regs
176    MOV $0, %CX
177 REG_LOOP3:
178    MOV $GRACON_ADDR, %dx
179    MOV %CL, %al
180    OUT %AL, %dx
181    call iodelay
182 
183    MOV $GRACON_ADDR, %dx
184    INC %DX
185    MOV (%si), %AL
186    OUT %AL, %dx
187    call iodelay
188 
189    INC %SI
190    INC %CX
191    CMP $9, %CL
192    JL REG_LOOP3
193 
194    MOV $STATUS_ADDR, %dx
195    IN %DX, %al
196    call iodelay
197 
198    # Send ATTRCON regs
199    MOV $0, %cx
200 REG_LOOP4:
201    MOV $ATTRCON_ADDR, %dx
202    IN %DX, %ax
203 
204    MOV %CL, %al
205    OUT %AL, %dx
206    call iodelay
207 
208    MOV (%si), %AL
209    OUT %AL, %dx
210    call iodelay
211 
212    INC %SI
213    INC %CX
214    CMP $21, %CL
215    JL REG_LOOP4
216 
217    MOV $0x20, %al
218    OUT %AL, %dx
219    call iodelay
220    RET
221 #SETMODE ENDP
222 SET_OUT:
223   CALL SETPALETTE
224   #POP %BP
225   RET
226 
227 iodelay:
228   nop
229   nop
230   nop
231   nop
232   ret
233 
234 SETPALETTE:
235    # Address of the 6-byte array
236    MOV $PALETTE, %di
237 
238    MOV $0, %ECX
239 PAL_LOOP:
240    MOV %CX, %ax
241    # Send color
242    MOV $0x03C8, %dx
243    OUT %AL, %dx
244 
245    # Write R value
246    MOV $0x03C9, %dx
247    movb (%DI), %al
248    OUT %AL, %dx
249 
250    # Write G value
251    MOV $0x03C9, %dx
252    movb 1(%DI), %al
253    OUT %AL, %dx
254 
255    # Write B value
256    MOV $0x03C9, %dx
257    movb 2(%DI), %al
258    OUT %AL, %dx
259 
260    ADD $3, %di
261    INC %CX
262    CMP $16, %CX
263    JLE PAL_LOOP
264 
265    RET
266 
267 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
268 #=- VGA register variables for the various videomodes                       -=
269 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
270 
271 #if 0
272 MODE03H:
273 .byte 0x67,0x00,0x03,0x00,0x03,0x00,0x02
274 .byte 0x5F,0x4F,0x50,0x82,0x55,0x81,0x0BF,0x1F,0x00,0x4F,0x0E,0x0F,0x00,0x00,0x00,0x00
275 .byte 0x9C,0x0E,0x8F,0x28,0x01,0x96,0x0B9,0x0A3,0x0FF
276 .byte 0x00,0x00,0x00,0x00,0x00,0x10,0x0E,0x00,0x0FF
277 .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
278 .byte 0x0C,0x00,0x0F,0x08,0x00
279 #endif
280 
281 
282 MODE10H:
283 .byte 0xA3,0x00,0x03,0x01,0x0F,0x00,0x06
284 .byte 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0BF,0x1F,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00
285 .byte 0x83,0x85,0x5D,0x28,0x0F,0x63,0x0BA,0x0E3,0x0FF
286 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,0x0FF
287 .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
288 .byte 0x01,0x00,0x0F,0x00,0x00
289 
290 MODE12H:
291 .byte 0x0E3, 0x00, 0x03, 0x01, 0x0F, 0x00, 0x06
292 .byte 0x5F,0x4F,0x50,0x82,0x54,0x80,0x0B,0x3E,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x59
293 .byte 0xEA,0x8C,0x0DF,0x28,0x00,0x0E7,0x04,0x0E3,0x0FF
294 .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0F,0x0FF
295 .byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F
296 .byte 0x01,0x00,0x0F,0x00,0x00
297 
298 PALETTE:
299 .byte   0,  0,  0,  0,  0, 42,  0, 42,  0,  0, 42, 42, 42,  0,  0
300 .byte 42,  0, 42, 42, 21,  0, 42, 42, 42, 21, 21, 21, 21, 21, 63, 21, 63, 21
301 .byte 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63
302 
303 

↓ qemu snapshot

 

程式的 vga register read/write 我還不清楚, 應該會對照著 vga/super vga 技術手冊這本書來研究, vga 還真不是普通的複雜。

 

simple_os vga branch 可以測試這段程式:

git clone git@github.com:descent/simple_os.git
cd simple_os
git checkout origin/vga -b vga

ref:
  1. http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/
  2. http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/MAIN.ASM
  3. http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/README.TXT
  4. http://bos.asmhackers.net/docs/vga_without_bios/snippet_1/modsrc30/USAGE.TXT
  5. 之前失敗的文章: http://descent-incoming.blogspot.tw/2011/10/vga-biso.html
  6. http://forum.osdev.org/viewtopic.php?f=13&t=25307 (有 640X480X256 color example)

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。