[英]How to use VESA mode in vmware or Virtualbox?
我正在從頭開始構建自己的操作系統。 我閱讀了 VESA 教程並編寫了一個程序來切換到 VESA 模式,然后將屏幕變白。 (Stage1.asm 是一個簡單地加載和執行 kernel 的程序。)
Stage2.asm
[BITS 16]
MOV AX, 800
MOV BX, 600
MOV CL, 32
CALL vbe_set_mode
JMP Fill
vbe_set_mode:
mov [.width], ax
mov [.height], bx
mov [.bpp], cl
sti
push es
mov ax, 0x4F00
mov di, vbe_info
int 0x10
pop es
cmp ax, 0x4F
jne .error
mov ax, word[vbe_info.video_modes]
mov [.offset], ax
mov ax, word[vbe_info.video_modes+2]
mov [.segment], ax
mov ax, [.segment]
mov fs, ax
mov si, [.offset]
.find_mode:
mov dx, [fs:si]
add si, 2
mov [.offset], si
mov [.mode], dx
mov ax, 0
mov fs, ax
push dx
mov dx, 0xFFFF
cmp [.mode], dx
pop dx
je .error
push es
mov ax, 0x4F01
mov cx, [.mode]
mov di, vbe_mode_info
int 0x10
pop es
cmp ax, 0x4F
jne .error
mov ax, [.width]
cmp ax, [vbe_mode_info.width]
jne .next_mode
mov ax, [.height]
cmp ax, [vbe_mode_info.height]
jne .next_mode
mov al, [.bpp]
cmp al, [vbe_mode_info.bpp]
jne .next_mode
mov ax, [.width]
mov word[vbe_screen.width], ax
mov ax, [.height]
mov word[vbe_screen.height], ax
mov eax, [vbe_mode_info.framebuffer]
mov dword[vbe_screen.physical_buffer], eax
mov ax, [vbe_mode_info.pitch]
mov word[vbe_screen.bytes_per_line], ax
mov eax, 0
mov al, [.bpp]
mov byte[vbe_screen.bpp], al
shr eax, 3
mov dword[vbe_screen.bytes_per_pixel], eax
mov ax, [.width]
shr ax, 3
dec ax
mov word[vbe_screen.x_cur_max], ax
mov ax, [.height]
shr ax, 4
dec ax
mov word[vbe_screen.y_cur_max], ax
; Set the mode
push es
mov ax, 0x4F02
mov bx, [.mode]
or bx, 0x4000 ; enable LFB
mov di, 0 ; not sure if some BIOSes need this... anyway it doesn't hurt
int 0x10
pop es
cmp ax, 0x4F
jne .error
clc
ret
.next_mode:
mov ax, [.segment]
mov fs, ax
mov si, [.offset]
jmp .find_mode
.error:
LEA SI, MsgNoVESA
CALL Print
jmp $
.width dw 0
.height dw 0
.bpp db 0
.segment dw 0
.offset dw 0
.mode dw 0
vbe_screen:
.width dw 0
.height dw 0
.bpp dw 0
.physical_buffer db 0
.bytes_per_pixel dw 0
.bytes_per_line dw 0
.x_cur_max dw 0
.y_cur_max dw 0
vbe_info:
.signature db "VESA"
.version dw 0
.oem dd 0
.capabilities dd 0
.video_modes dd 0
.video_memory dw 0
.software_rev dw 0
.vendor dd 0
.product_name dd 0
.product_rev dd 0
.reserved db 222 dup 0
.oem_data db 256 dup 0
vbe_mode_info:
.attributes dw 0
.window_a db 0
.window_b db 0
.granularity dw 0
.window_size dw 0
.segment_a dw 0
.segment_b dw 0
.win_func_ptr dd 0
.pitch dw 0
.width dw 0
.height dw 0
.w_char db 0
.y_char db 0
.planes db 0
.bpp db 0
.banks db 0
.memory_model db 0
.bank_size db 0
.image_pages db 0
.reserved0 db 0
.red_mask db 0
.red_position db 0
.green_mask db 0
.green_position db 0
.blue_mask db 0
.blue_position db 0
.reserved_mask db 0
.reserved_position db 0
.direct_color_attributes db 0
.framebuffer dd 0
.off_screen_mem_off dd 0
.off_screen_mem_size dw 0
.reserved1 db 206 dup 0
Fill:
MOV EBX, [vbe_mode_info.framebuffer]
MOV EAX, [vbe_mode_info.framebuffer]
ADD EAX, 800 * 600 * 4
MOV ECX, 0x00FFFFFF
MOV EDX, 0
FillLoop:
MOV [EBX], ECX
ADD EBX, 4
CMP EBX, EAX
JA EndFunc
JMP FillLoop
EndFunc:
CLI
HLT
MsgNoVESA: db "This PC is not support VESA.", 0x00
該程序適用於 QEMU,但不適用於 vmware 或 Virtualbox。 為什么這個程序只能在 QEMU 上運行?
我在代碼中發現了幾個錯誤:
mov eax, [vbe_mode_info.framebuffer] mov dword[vbe_screen.physical_buffer], eax
在字節大小的變量.physical_buffer db 0
中寫入dword 。
mov eax, 0 mov al, [.bpp] mov byte[vbe_screen.bpp], al shr eax, 3 mov dword[vbe_screen.bytes_per_pixel], eax
在字大小的變量.bytes_per_pixel dw 0
中寫入一個dword 。 這會破壞指向線性幀緩沖區的指針,這會在寫入 memory 時產生災難性的結果
您永遠不會檢查 VESA 版本。 盡管如此,您還是應該這樣做,因為您需要的幀緩沖區指針PhysBasePtr僅包含在 VESA 2.0 版及更高版本的 ModeInformation 塊中。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.