21,459
社区成员
发帖
与我相关
我的任务
分享
;---------------------------------------------------------------------
; void Dectect_Video()
Global Dectect_Video
Dectect_Video:
; 返回 VBE 控制器信息
mov ax,VBE_INFO_BLOCK
mov es,ax
mov di,0x0
mov ax,0x4f00
int 0x10
; 检测调用是否成功
cmp ax,VBE_CALL_SUCCESSFUL
jnz .dead
; 保存显存大小
mov ax,word [es:di+memory_size]
mov word [sdb + vmemory_size],ax
; 保存水平分辨率
mov ax,0x0320
mov word [sdb + screen_width],ax
; 保存垂直分辨率
mov ax,0x0258
mov word [sdb + screen_height],ax
; 保存色彩深度
mov al,0x20
mov byte [sdb + bpp],al
mov ax,word [es:di + VideoModePtr + 2]
mov si,word [es:di + VideoModePtr + 0]
mov es,ax
mov di,si
; 开始遍历该系统所支持的显示模式
; 查找其中是否存在合适的显示模式值
;
.while:
mov ax,word [es:di]
cmp ax,0xffff
jz .endWhile
; 部分寄存器保存
push es
push di
; 查询详细模式信息
mov cx,word [es:di]
mov ax,VBE_INFO_BLOCK
mov es,ax
mov di,0x0400
mov ax,0x4f01
int 0x10
; 按下列条件查找显示模式号
cmp word [es:di+XResolution],800
jnz .continueWhile
cmp word [es:di+YResolution],600
jnz .continueWhile
cmp byte [es:di+BitsPerPixel],32
jnz .continueWhile
; 找到合适显示模式
; 保存线性内存地址到系统信息结构体
mov eax,dword [es:di + PhysBasePtr]
mov dword [sdb + phys_base_ptr],eax
; 获取VESA VBE的保护模式接口
mov ax,0x4f0a
mov bx,0x0
int 0x10
xor eax,eax
mov ax,es
shl eax,4
add ax,di
mov [sdb + pm_code],eax
mov ax,word [es:di]
mov [sdb + set_window],ax
pop di
pop es
; 保存显示模式号到系统信息结构体
mov ax,word [es:di]
mov word [sdb + vbe_mode],ax
jmp .endWhile
; 该轮循环未找到合适的显示模式
; 继续循环
.continueWhile:
pop di
pop es
add di,2
jmp .while
; 查找成功,返回
.endWhile:
ret
.dead:
push msg_get_vess_err
call Error
;---------------------------------------------------------------------
; void Entern_VESA_Mode()
Global Entern_VESA_Mode
Entern_VESA_Mode:
mov ax,0x4f02
mov bx,word [sdb + vbe_mode]
int 0x10
; 检测调用是否成功
cmp ax,VBE_CALL_SUCCESSFUL
jnz .dead
ret
.dead:
push msg_enter_vess_mode_err
call Error
// 下面将画点函数精简了一下,方便各位高手阅读,帮小弟指出问题所在
void Set_Pixel(s32 x,s32 y,u32 color)
{
u32 *p = sdb.phys_base_ptr + (sdb.screen_width*y+x);
*p = color;
}
;---------------------------------------------------------------------
; cpu.asm
; void Enable_PM()
; 本函数用于开启系统32位保护模式
Enable_PM:
; 移动kernel_gdt到GDT_ENTRY
; 其中6为gdt项个数
mov ax,ds
mov es,ax
cld
mov esi,kernel_gdt
mov edi,GDT_ENTRY
mov ecx,6*2
rep movsd
cli ; 关闭中断
lgdt [gdt_descriptor] ; 加载GDT描述符
; 开启A20地址线
in al,92h
or al,00000010b
out 92h,al
; 开启保护模式
mov eax,cr0
or eax,1
mov cr0,eax
jmp dword KERNEL_CS:Init_Data_Segment ; 正式进入保护模式
;---------------------------------------------------------------------
; start.asm
; void Init_Data_Segment()
; 初始化段寄存器
Init_Data_Segment:
mov ax,KERNEL_DS
mov ds,ax
mov es,ax
mov gs,ax
mov fs,ax
mov ss,ax
mov esp,dword [sdb + memory_size]
// 变量部分
GdtDescriptor gdt_descriptor = {0xffff,(Gdt *) GDT_ENTRY}; // 全局描述符描述符
u64 kernel_gdt[6] = {\
0x0,\
0x00cf9a000000ffff,\
0x00cf92000000ffff,\
0x00cffa000000ffff,\
0x00cff2000000ffff,\
0x0000890000000068\
}; // 全局描述符表