想必大家都看过这篇教程吧【图片】Haribote OS 实现真彩色教程【30天自制操作系统吧】_百度贴吧 (baidu.com)
应该吧里有很多人脱离了30days的工具链 用了新版的qemu 或者其他虚拟机,那么再来看这篇教程,就有些不通用了,用新版的qemu的吧友,可能照着这篇教程做完,发现还是有问题(显示有问题),其实,你是切换到了24位模式,帖子里是32位模式啊?因为每个VESA显示卡的VBE模式功能号 都不一样,所以,更可靠的方法是枚举所有的VBE功能号,然后判断宽 高 色深
我这里写了一份,大家可以直接拿去用(比如放到asmhead中)
但是有个注意事项,别忘了重新为boot info赋值 因为我用的es和书里不一样,至于在哪里添加这样的代码,我就不多说了,相信想要做真彩色切换的各位都是有一定代码能力的吧,如果实在找不到的话,那就留言吧,看到了我都会回复的qaq
另外,我用的是汇编 而且是nasm汇编,要想直接在nask用还得修改修改(注意,我这里为了方便调试,所以写成了一个引导扇区,用的时候记得把不必要的东西删掉)
好了,上代码
jmp start
%define w 1024
%define h 768
%define bpp 32
start:
mov ax,0x7c0
mov ds,ax
mov es,ax
mov ax,0x0
mov ss,ax
mov sp,0x7c00
call set_mode
jmp $
set_mode:
mov ax,0x7e0
mov es,ax
mov ax,0x4f00
mov di,0x0
int 10h
mov ax,0
mov dword eax,[es:14]
and eax,0xffff0000
shr eax,16
mov es,ax
mov dword eax,[es:14]
and eax,0x0000ffff
mov di,ax
;jmp $
; 此时 es:di 就是MODE
.lp:
mov word ax,[es:di]
;jmp $
cmp ax,0xffff
je .end
add di,2
call cmp_and_sw
jz .end
jmp .lp
.end:
ret
get_info:
pushad
;push es
mov ax,0x0700
mov es,ax
mov ax,0x4f01
add cx,0x4000
mov di,0x0
int 10h
;pop es
popad
ret
cmp_and_sw:
pushad
push es
mov cx,ax
call get_info
mov ax,0x0700
mov es,ax
mov word ax,[es:18]
;jmp $
cmp ax,w
jne .end1
mov word ax,[es:20]
cmp ax,h
jne .end1
mov byte al,[es:25]
cmp al,bpp
jne .end1
jmp .end2
.end1:
pop es
popad
cmp dword esp,0xffffffff ;现在是实模式 ESP 不可能会大于0xffff 所以我们能肯定ZF=0
ret
.end2:
mov ax,4f02h
add cx,0x4000
mov bx,cx
int 10h
pop es
popad
cmp ax,ax ;设置ZF标志位(ax和他本身肯定是相等的 所以我们能肯定ZF=1)
ret
times 510-($-$$) db 0
dw 0xaa55
度过了这一步,其他地方就和那篇帖子里一样了 awa
应该吧里有很多人脱离了30days的工具链 用了新版的qemu 或者其他虚拟机,那么再来看这篇教程,就有些不通用了,用新版的qemu的吧友,可能照着这篇教程做完,发现还是有问题(显示有问题),其实,你是切换到了24位模式,帖子里是32位模式啊?因为每个VESA显示卡的VBE模式功能号 都不一样,所以,更可靠的方法是枚举所有的VBE功能号,然后判断宽 高 色深
我这里写了一份,大家可以直接拿去用(比如放到asmhead中)
但是有个注意事项,别忘了重新为boot info赋值 因为我用的es和书里不一样,至于在哪里添加这样的代码,我就不多说了,相信想要做真彩色切换的各位都是有一定代码能力的吧,如果实在找不到的话,那就留言吧,看到了我都会回复的qaq
另外,我用的是汇编 而且是nasm汇编,要想直接在nask用还得修改修改(注意,我这里为了方便调试,所以写成了一个引导扇区,用的时候记得把不必要的东西删掉)
好了,上代码
jmp start
%define w 1024
%define h 768
%define bpp 32
start:
mov ax,0x7c0
mov ds,ax
mov es,ax
mov ax,0x0
mov ss,ax
mov sp,0x7c00
call set_mode
jmp $
set_mode:
mov ax,0x7e0
mov es,ax
mov ax,0x4f00
mov di,0x0
int 10h
mov ax,0
mov dword eax,[es:14]
and eax,0xffff0000
shr eax,16
mov es,ax
mov dword eax,[es:14]
and eax,0x0000ffff
mov di,ax
;jmp $
; 此时 es:di 就是MODE
.lp:
mov word ax,[es:di]
;jmp $
cmp ax,0xffff
je .end
add di,2
call cmp_and_sw
jz .end
jmp .lp
.end:
ret
get_info:
pushad
;push es
mov ax,0x0700
mov es,ax
mov ax,0x4f01
add cx,0x4000
mov di,0x0
int 10h
;pop es
popad
ret
cmp_and_sw:
pushad
push es
mov cx,ax
call get_info
mov ax,0x0700
mov es,ax
mov word ax,[es:18]
;jmp $
cmp ax,w
jne .end1
mov word ax,[es:20]
cmp ax,h
jne .end1
mov byte al,[es:25]
cmp al,bpp
jne .end1
jmp .end2
.end1:
pop es
popad
cmp dword esp,0xffffffff ;现在是实模式 ESP 不可能会大于0xffff 所以我们能肯定ZF=0
ret
.end2:
mov ax,4f02h
add cx,0x4000
mov bx,cx
int 10h
pop es
popad
cmp ax,ax ;设置ZF标志位(ax和他本身肯定是相等的 所以我们能肯定ZF=1)
ret
times 510-($-$$) db 0
dw 0xaa55
度过了这一步,其他地方就和那篇帖子里一样了 awa