我正在从头开始构建我自己的操作系统。我阅读了VESA教程,并编写了一个程序来切换到VESA模式,然后将屏幕变成白色。(Stage1.asm是一个简单地加载和执行内核的程序。)
阶段2.
[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上工作?
发布于 2022-07-03 18:28:17
我在代码中发现了几个错误:
mov eax,vbe_mode_info.framebuffer mov dwordvbe_screen.physical_buffer,eax
在字节大小的变量 .physical_buffer db 0中写入dword。
mov eax,0 mov al,.bpp mov bytevbe_screen.bpp,al shr eax,3 mov dwordvbe_screen.bytes_per_pixel,eax
在字大小的变量 .bytes_per_pixel dw 0中写入dword。这会破坏指向线性帧缓冲区的指针,这会在写入内存时产生灾难性的结果!
你从来没有检查过VESA版本。尽管如此,您还是应该这样做,因为您需要的框架缓冲区指针PhysBasePtr只包含在VESA2.0版本和更高版本的ModeInformation块中。
https://stackoverflow.com/questions/72843939
复制相似问题