|
楼主 |
发表于 2003-6-28 22:41:14
|
显示全部楼层
不好意思,各位,其实昨天已经弄好了,只是一直看租来的连续剧,一口气看了20多集,刚刚睡醒,呵呵。
to jjww
0x000b8000是显存的位置,也许在缺省的图形模式可以直接使用,pc的资料太古怪太枯燥了,看得人好烦,各种资料的解释只有一个,为了照顾向下兼容才有这么许多古里古怪的内容,有的时候觉得反正现在也没有人再用,还留着他们干嘛
to tielian
谢谢你一块调程序,gdt_fixup是不能删的,因为这个过程才是初始化gdt表的内容
我简单解释一下
在保护模式下,gdt表里一项是8个字节,其中的第3,4,5,8组成一个段的32位基地址。进入保护模式之前,要把一个6字节的内容装载到gdtr寄存器里说明gdt表的基地址,表长和属性,程序里把它保存到了gdtarg里。gdt_fixup的功能就是把实模式下的各段地址写到gdt表里去并为gdtarg设置真正的值。
好像是我对sp的初始化有问题,所以我把它删了就没事了,改进后的程序如下:
[code:1]
#define CR0_PE 1
.text
.code16
.globl _start
_start:
jmp start0
nop
mesg1:
.ascii "Loading...... "
mesg2:
.ascii "Ready........ "
##################### idt ########################
idt:
.word 0
.word 0, 0
##################### gdt ########################
.align 16
gdt:
.word 0, 0
.byte 0, 0x00, 0x00, 0
bootcodeseg = . - gdt
.word 0xffff, 0
.byte 0, 0x9e, 0x4f, 0
bootdataseg = . - gdt
.word 0xffff, 0
.byte 0, 0x92, 0x4f, 0
videoseg = . - gdt
.word 0x3999, 0x8000
.byte 0x0b, 0x92, 0x00, 0x00
bootrealseg = . - gdt
.word 0xffff, 0
.byte 0, 0x9e, 0x00, 0
bootrealdata = . - gdt
.word 0xffff, 0
.byte 0, 0x92, 0x00, 0
gdtlen = . - gdt
.align 16
gdtarg:
.word gdtlen-1 /* limit */
.long 0 /* physical addr, will be inserted */
ourseg: .word 0 /* real mode code and data segment */
stkseg: .word 0 /* real mode stack segment */
stkdif: .long 0 /* diff. between real and prot sp */
#
# start of code
#
start0:
mov %cs, %ax /* don't trust values of ds, es or ss */
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
# mov $0xfffc, %sp
xor %ax, %ax /* in particular ah = 0 */
int $0x13
call clrscr
movw $mesg1,%bp
call prt_msg
call get_key
call clrscr
call gdt_fixup
movw $mesg2,%bp
call prt_msg
call get_key
call clrscr
call real_to_prot
loop:
jmp loop
gdt_fixup:
.code16
pushw %ax
pushw %dx
xorl %eax, %eax
mov %cs, %ax
mov %ax, ourseg
/* sort out stuff for %ss != %ds */
movw %ss, %dx
movw %dx, stkseg
subw %ax, %dx
shll $16, %edx
shrl $12, %edx
movl %edx, stkdif
/* fix up GDT entries for bootstrap */
mov %ax, %dx
shll $4, %eax
shr $12, %dx
#define FIXUP(gdt_index) \
movw %ax, gdt+gdt_index+2; \
movb %dl, gdt+gdt_index+4
FIXUP(bootcodeseg)
FIXUP(bootrealseg)
FIXUP(bootdataseg)
/* fix up GDT pointer */
addl $gdt, %eax
movl %eax, gdtarg+2
pop %dx
pop %ax
ret
real_to_prot:
.code16
pushl %eax
cli
lidt %cs:idt
lgdt %cs:gdtarg /* Global descriptor table */
movl %cr0, %eax
or $CR0_PE, %ax
movl %eax, %cr0 /* Enter 'protected mode' */
ljmp $bootcodeseg, $1f /* Jump into a 32bit segment */
1:
.code32
dbg:
jmp dbg
/* Set all the segment registers to map the same area as the code */
mov $bootdataseg, %eax
mov %ax, %ds
mov %ax, %es
mov %ax, %ss
addl stkdif, %esp /* Allow for real %ss != %ds */
mov $videoseg, %eax
mov %ax, %gs
movw $0x741,%gs:0
spin:
jmp spin
popl %eax
ret
prt_msg:
.code16
movb $0x13,%ah
movb $0x00,%al
movw $0x0007,%bx
movw $0x14,%cx
movw $0x0000,%dx
int $0x10
ret
get_key:
.code16
movb $0x00,%ah
int $0x16
ret
clrscr:
.code16
movw $0x0600,%ax
movw $0x0000,%cx
movw $0x174f,%dx
movb $0x0, %bh
int $0x10
ret
.org 510
boot_flag:
.word 0xAA55
[/code:1]
因为我是使用
movw $0x741,%gs:0
这段代码来写显存,所以应该认为是使用的保护模式 |
|