如何在VMware或VirtualBox中使用VESA模式?

发布于 2025-02-12 10:58:38 字数 3701 浏览 2 评论 0原文

我正在从头开始构建自己的操作系统。 我阅读了VESA教程,并编写了一个程序以切换到VESA模式,然后将屏幕变白。 (stage1.asm是一个简单地加载和执行内核的程序。)

stage2.sm.2.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?

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.
(Stage1.asm is a program that simply loads and executes the 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

This program works on QEMU, but not on vmware or Virtualbox.
Why does this program only work on QEMU?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迷爱 2025-02-19 10:58:38

我在代码中发现了几个错误:

  mov eax,[vbe_mode_info.framebuffer]
mov dword [vbe_screen.physical_buffer],eax
 

在A dword 中写入字节大小的变量 .physical_buffer db 0

  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 。这损坏了指向线性框架缓冲区的指针,该线性框架缓冲区可能在写入内存后会产生灾难性的结果!


您永远不会检查VESA版本。尽管如此,您还是应该因为所需的FrameBuffer Pointer physbaseptr 仅包含在VESA版本2.0及更好的ModeInformation块中。

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.

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. This corrupts the pointer to the Linear Frame Buffer which can produce disastrous results upon writing to memory!


You never check the VESA version. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文