[英]How to use VESA mode in vmware or Virtualbox?
I am building my own OS from scratch.我正在从头开始构建自己的操作系统。 I read the VESA tutorial and wrote a program to switch to VESA mode and then turn the screen white.
我阅读了 VESA 教程并编写了一个程序来切换到 VESA 模式,然后将屏幕变白。 (Stage1.asm is a program that simply loads and executes the kernel.)
(Stage1.asm 是一个简单地加载和执行 kernel 的程序。)
Stage2.asm 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
This program works on QEMU, but not on vmware or Virtualbox.该程序适用于 QEMU,但不适用于 vmware 或 Virtualbox。 Why does this program only work on QEMU?
为什么这个程序只能在 QEMU 上运行?
I found a couple of errors in the code:我在代码中发现了几个错误:
mov eax, [vbe_mode_info.framebuffer] mov dword[vbe_screen.physical_buffer], eax
writes a dword in a byte-sized variable .physical_buffer db 0
.在字节大小的变量
.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
writes a dword in a word-sized variable .bytes_per_pixel dw 0
.在字大小的变量
.bytes_per_pixel dw 0
中写入一个dword 。 This corrupts the pointer to the Linear Frame Buffer which can produce disastrous results upon writing to memory这会破坏指向线性帧缓冲区的指针,这会在写入 memory 时产生灾难性的结果
You never check the VESA version.您永远不会检查 VESA 版本。 You should nonetheless because the framebuffer pointer PhysBasePtr that you need, is only included in the ModeInformation block for VESA versions 2.0 and better.
尽管如此,您还是应该这样做,因为您需要的帧缓冲区指针PhysBasePtr仅包含在 VESA 2.0 版及更高版本的 ModeInformation 块中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.