进入保护模式的程序,可惜是要大家帮忙给看看什么地方出错了
原程序#define CR0_PE 1
.text
.code16
.globl _start
_start:
jmpstart0
nop
mesg1:
.ascii "Loading...... "
mesg2:
.ascii "Ready........ "
##################### idt ########################
idt:
.word 0
.word 0, 0
##################### gdt ########################
.align16
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,0x000b8000
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
make文件
boot : bootp.out
objcopy -S -O binary bootp.out boot
bootp.out : bootp.o
ld -nostdlib -static -N -e _start -Ttext 0x7c00 -o bootp.out bootp.o
bootp.o : _bootp.S
as -o bootp.o _bootp.S
_bootp.S : bootp.S
cc -o _bootp.S -E bootp.S
clean :
rm -rf bootp.o bootp.out _bootp.S
install :
dd bs=512 if=boot of=/dev/fd0
功能:
启动,打印字符串,按任意键继续,最后在保护模式下显示一个A
问题:
我在ljmp下放了一条死循环,用来debug,因为一进行跳转系统就重启。
使用方法:
make编译
make clean 删除中间文件
make install 写入软盘
那位精通一块研究一下啊,特别是两位斑竹... sorry, no idea on this. i am poor at asm code.
can jjww try this?:-D :oops:
我也比较弱。我想我没有时间做测试。你有什么问题,是什么方面看不懂,说具体点,我们一起讨论。 movw $0x741,0x000b8000
这句话有点迷惑,和普通BIOS显示中断调用(int)不一样,
不知道显卡的BIOS调用什么规范的,我想这就是打印的‘A’的意思吧。不知道猜对没? 我用的djgpp,去掉了gdt_fixup我觉得没必要
#define CR0_PE 1
.text
.code16
.globl _start
_start:
jmpstart0
nop
mesg1:
.ascii "Loading...... "
mesg2:
.ascii "Ready........ "
##################### idt ########################
idt:
.word 0
.word 0, 0
##################### gdt ########################
# .align16
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 gdt /* 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
real_to_prot:
.code16
pushl %eax
cli
lidt idt
lgdt gdtarg /* Global descriptor table */
movl %cr0, %eax
or $0x1, %al
movl %eax, %cr0 /* Enter 'protected mode' */
ljmp $bootcodeseg, $1f /* Jump into a 32bit segment */
1:
.code32
/*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,0x000b8000
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 不好意思,各位,其实昨天已经弄好了,只是一直看租来的连续剧,一口气看了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的初始化有问题,所以我把它删了就没事了,改进后的程序如下:
#define CR0_PE 1
.text
.code16
.globl _start
_start:
jmpstart0
nop
mesg1:
.ascii "Loading...... "
mesg2:
.ascii "Ready........ "
##################### idt ########################
idt:
.word 0
.word 0, 0
##################### gdt ########################
.align16
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
因为我是使用
movw $0x741,%gs:0
这段代码来写显存,所以应该认为是使用的保护模式 呵呵,你应该没看到我以经将gdtr初始化了吧
gdtarg:
.word gdtlen-1 /* limit */
.long gdt /* physical addr, will be inserted */ sorry,不好意思,没仔细看
但是gdt表的内容还没有初始化,尤其是
bootcodeseg = . - gdt
.word 0xffff, 0
.byte 0, 0x9e, 0x4f, 0
这一段,没有填值,填完以后应该是
bootcodeseg = . - gdt
.word 0xffff, 0x000c
.byte 0007, 0x9e, 0x4f, 0
你编译的程序可以运行吗? 我先问你个问题,在你这个程序中cs=?如果你知道了,就明白
这个是错误的
bootcodeseg = . - gdt
.word 0xffff, 0x000c
.byte 0007, 0x9e, 0x4f, 0 cs的值是0x7c00,因为那个长跳转是使用bootcodeseg里的数据进行的,所以在ljmp之前不往bootcodeseg里填入正确的值是会出错的,那个宏FIXUP就是要把cs的值正确填入gdt里的各个描述符里。 cs=0x0!
你可以自行验正。
bios将boot sector装载到0:0x7c00! 不好意思,是我搞错了,初始化时是ip的值是7c00.
在这个程序里,使用fixup函数确实是多此一举,呵呵 强,不过我还暂时看不懂
页:
[1]