|
自己写了一个保护模式的程序,有两个任务,分别切换,但是每次系统调用返回的时候,代码就跑飞,大家帮忙看看。
程序如下:
boot.s文件:
BOOTSEG = 0x07c0
SYSSEG = 0x1000
SYSLEN = 17
entry start
start:
jmpi go, #BOOTSEG
go:
!初始化段基址
mov ax, cs
mov ds, ax
mov ss, ax
mov sp, #0x400
!从硬盘中获取加载内核到内存中
!DH,磁头号,DL,驱动器号
!CH,磁道号,CL,磁道号,扇区号
!ES:BX,缓冲区位置
!AH:功能号,AL:读取扇区数
mov dh, #0x00
mov dl, #0x00
mov ch, #0x00
mov cl, #0x02
mov ax, #SYSSEG
mov es, ax
mov bx, #0x0000
mov ah, #0x02
mov al, #SYSLEN
int 0x13
jnc ok_load
die:
jmp die
!加载成功
ok_load:
!关闭中断,下面的程序将覆盖中断服务程序
cli
mov al,#0x11 ! initialization sequence
out #0x20,al ! send it to 8259A-1
out #0xA0,al ! and to 8259A-2
mov al,#0x20 ! start of hardware int's (0x20)
out #0x21,al
mov al,#0x28 ! start of hardware int's 2 (0x28)
out #0xA1,al
mov al,#0x04 ! 8259-1 is master
out #0x21,al
mov al,#0x02 ! 8259-2 is slave
out #0xA1,al
mov al,#0x01 ! 8086 mode for both
out #0x21,al
out #0xA1,al
mov al,#0xFF ! mask off all interrupts for now
out #0x21,al
out #0xA1,al
mov ax, #SYSSEG
mov ds, ax
mov si, #0x00
mov di, #0x00
mov ax, #0x0000
mov es, ax
mov cx, #0x1000
rep
movw
mov ax,#BOOTSEG
mov ds,ax
lidt idt_48
lgdt gdt_48
mov ax,#0x0001
lmsw ax
jmpi 0,8
gdt:
.word 0,0,0,0 !段描述符0不用
.word 0x07ff
.word 0x0000
.word 0x9A00
.word 0x00C0
.word 0x07ff
.word 0x0000
.word 0x9200
.word 0x00C0
idt_48:
.word 0x0000
.word 0x0000, 0x0000
gdt_48:
.word 0x07ff
.word 0x7c00+gdt, 0x0000
.org 510
.word 0xAA55 !扇区有效位标识
head.s文件:
.text
startup_32:
#设置数据段选择符
movl $0x10, %eax
movl %ax, %ds
#设置堆栈段选择符
lss init_stack, %esp
call setup_idt
call setup_gdt
call setup_timer
#模拟任务0被中断的场景,设置栈中的内容
pushfl
andl $0xffffbfff, (%esp)
popfl
movl $0x20,%eax
ltr %ax
movl $0x28,%eax
lldt %ax
movl $0, current
sti
pushl $0x17
pushl $init_stack
pushfl
pushl $0x0f
pushl $task0
iret
#使用current变量记录目前运行那个任务
current:
.long 0
scr_loc:
.long 0
#setup_idt函数代码
setup_idt:
lea ignore_int, %edx
movl $0x00080000, %eax
movw %dx, %ax
movw $0x8e00, %dx
lea idt, %edi
mov $256, %ecx
#设置idt表内容
rp_idt:
movl %eax, (%edi)
movl %edx, 4(%edi)
addl $8, %edi
dec %ecx
jne rp_idt
#设置时钟的中断段描述符
lea timer_interrupt, %edx
movl $0x00080000, %eax
movw %dx, %ax
movw $0x8e00, %dx
movl $0x08, %ecx
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
#设置系统调用中断描述符
lea system_interrupt, %edx
movl $0x00080000, %eax
movw %dx, %ax
movw $0xef00, %dx
movl $0x80, %ecx
lea idt(,%ecx,8), %esi
movl %eax,(%esi)
movl %edx,4(%esi)
#加载idtr寄存器
lidt lidt_opcode
ret
#默认的中断处理程序
.align 2
ignore_int:
push %ds
pushl %eax
movl $0x10, %eax
mov %ax, %ds
movl $67, %eax
call write_char
popl %eax
pop %ds
iret
#time的中断处理程序
.align 2
timer_interrupt:
push %ds
pushl %eax
movl $0x10, %eax
mov %ax, %ds
movb $0x20, %al
outb %al, $0x20
movl $1, %eax
cmpl %eax, current
je 1f
movl $1,current
ljmp $0x30, $0
jmp 2f
1:
movl $0,current
ljmp $0x20, $0
2: popl %eax
pop %ds
iret
#int 80x的中断处理程序
.align 2
system_interrupt:
push %ds
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
movl $0x10, %edx
mov %dx, %ds
call write_char
popl %eax
popl %ebx
popl %ecx
popl %edx
pop %ds
iret
#显示字符的函数
write_char:
push %gs
push %ebx
mov $0x18, %ebx
mov %bx,%gs
mov scr_loc,%bx
shl $1, %ebx
movb %al, %gs%ebx)
shr $1, %ebx
incl %ebx
cmpl $2000, %ebx
jb 1f
mov $0, %ebx
1: movl %ebx, scr_loc
popl %ebx
pop %gs
ret
setup_gdt:
lgdt lgdt_opcode
ret
#gdt表空间
lgdt_opcode:
.word (endgdt-gdt)-1
.long gdt
gdt:
.quad 0x0000000000000000
.quad 0x00c09a00000007ff
.quad 0x00c09200000007ff
.quad 0x00c0920080000002
.word 0x68,tss0,0xe900,0x0000
.word 0x40,ldt0,0xe200,0x0000
.word 0x68,tss1,0xe900,0x0000
.word 0x40,ldt1,0xe200,0x0000
endgdt:
#idt表空间
.align 3
idt:
.fill 256, 8, 0
lidt_opcode:
.word 256 * 8 - 1
.long idt
#内核栈空间
.fill 128,4,0
init_stack:
.long init_stack
.word 0x10
#任务0的TSS段内容
tss0:
.long 0 #前一个任务的TSS选择符
.long krn_stk0, 0x10 #内核堆栈初始值
.long 0x00, 0x00 #SS1,SP1的内容,没有使用
.long 0x00, 0x00 #SS2,SP2的内容,没有使用
.long 0x00 #CR3的内容,本程序没有使用分页机制
.long 0x0000 #EIP的内容,#下面数据动态区内容,设置为0即可
.long 0x0000 #EFLAGS的内容
.long 0x0000 #eax的内容
.long 0x0000 #ecx的内容
.long 0x0000 #edx的内容
.long 0x0000 #ebx的内容
.long 0x0000 #esp的内容
.long 0x0000 #ebp的内容
.long 0x0000 #esi的内容
.long 0x0000 #edi的内容
.long 0x0000 #es的内容
.long 0x0000 #cs的内容
.long 0x0000 #ss的内容
.long 0x0000 #ds的内容
.long 0x0000 #fs的内容
.long 0x0000 #gs的内容
.word 0x28 #ldt段选择符00101000,使用GDT表中的第5个表项
.word 0x00
.word 0x00
.word 0x1000 #
#任务0的LDT表内容
ldt0:
.quad 0x0000000000000000
.quad 0x00c0fa00000003ff #DPL为3,代码段
.quad 0x00c0f200000003ff #DPL为2,数据段
#用户任务0的内核级别堆栈
krn_stk0:
.fill 128, 4, 0
#任务1的TSS段内容
tss1:
.long 0 #前一个任务的TSS选择符
.long krn_stk1, 0x10 #内核堆栈初始值
.long 0x00, 0x00 #SS1,SP1的内容,没有使用
.long 0x00, 0x00 #SS2,SP2的内容,没有使用
.long 0x00 #CR3的内容,本程序没有使用分页机制
.long task1 #EIP的内容,#下面数据动态区内容,设置为0即可
.long 0x0200 #EFLAGS的内容
.long 0x0000 #eax的内容
.long 0x0000 #ecx的内容
.long 0x0000 #edx的内容
.long 0x0000 #ebx的内容
.long usr_stk1 #esp的内容
.long 0x0000 #ebp的内容
.long 0x0000 #esi的内容
.long 0x0000 #edi的内容
.long 0x0017 #es的内容
.long 0x0017 #cs的内容
.long 0x0017 #ss的内容
.long 0x0017 #ds的内容
.long 0x0017 #fs的内容
.long 0x0017 #gs的内容
.word 0x38 #ldt段选择符00101000,使用GDT表中的第5个表项
.word 0x00
.word 0x00
.word 0x1000 #
#任务1的LDT表内容
ldt1:
.quad 0x0000000000000000
.quad 0x00c0fa00000003ff #DPL为3,代码段
.quad 0x00c0f200000003ff #DPL为2,数据段
#用户任务1的内核级别堆栈
krn_stk1:
.fill 128, 4, 0
setup_timer:
movb $0x36, %al
movl $0x43, %edx
outb %al, %dx
movl $11930, %eax
movl $0x40, %edx
out %al, %dx
movb %ah, %al
outb %al, %dx
ret
#用户任务0的代码
task0:
movl $0x17, %eax
movw %ax, %ds
movl $65, %al
int $0x80
jmp task0
#用户任务0的任务级别堆栈
.fill 128,4,0
usr_stk0:
#用户任务1的代码
task1:
movl $66, %al
int $0x80
jmp task1
#用户任务1的任务级别堆栈
.fill 128,4,0
usr_stk1:
目前调试结果,运行到system_interrupt,pop %ds的时候,代码就开始异常跳转。
#int 80x的中断处理程序
.align 2
system_interrupt:
push %ds
pushl %edx
pushl %ecx
pushl %ebx
pushl %eax
movl $0x10, %edx
mov %dx, %ds
call write_char
popl %eax
popl %ebx
popl %ecx
popl %edx
pop %ds
iret
bochs调试结果:
<bochs:31> u /10
0000013d: ( ): pop eax ; 58
0000013e: ( ): pop ebx ; 5b
0000013f: ( ): pop ecx ; 59
00000140: ( ): pop edx ; 5a
00000141: ( ): pop ds ; 1f
00000142: ( ): iret ; cf
00000143: ( ): push gs ; 0fa8
00000145: ( ): push ebx ; 53
00000146: ( ): mov ebx, 0x18 ; bb18000000
0000014b: ( ): opsize mov gs, bx ; 668eeb
运行了pop ds后,就开始异常跳转了,没有执行iret。
(0) [0x0000013e] 0008:0000013e (unk. ctxt): pop ebx ; 5b
<bochs:36> step
Next at t=16156847
(0) [0x0000013f] 0008:0000013f (unk. ctxt): pop ecx ; 59
<bochs:37> step
Next at t=16156848
(0) [0x00000140] 0008:00000140 (unk. ctxt): pop edx ; 5a
<bochs:38> step
Next at t=16156849
(0) [0x00000141] 0008:00000141 (unk. ctxt): pop ds ; 1f
<bochs:39> info registers
eax 0x41 65
ecx 0x80 128
edx 0x40 64
ebx 0x0 0
esp 0xc3c 0xc3c
ebp 0x0 0x0
esi 0x5c8 1480
edi 0x9c8 2504
eip 0x141 0x141
eflags 0x247 583
cs 0x8 8
ss 0x10 16
ds 0x10 16
es 0x0 0
fs 0x0 0
gs 0x0 0
<bochs:40> dump_cpu
eax:0x41
ebx:0x0
ecx:0x80
edx:0x40
ebp:0x0
esi:0x5c8
edi:0x9c8
esp:0xc3c
eflags:0x247
eip:0x141
cs:s=0x8, dl=0x7ff, dh=0xc09a00, valid=1
ss:s=0x10, dl=0x7ff, dh=0xc09200, valid=7
ds:s=0x10, dl=0x7ff, dh=0xc09200, valid=7
es:s=0x0, dl=0x0, dh=0x0, valid=0
fs:s=0x0, dl=0x0, dh=0x0, valid=0
gs:s=0x0, dl=0x0, dh=0x0, valid=0
ldtr:s=0x28, dl=0xc3c0040, dh=0xe200, valid=1
tr:s=0x20, dl=0xbd40068, dh=0xe900, valid=1
gdtr:base=0x182, limit=0xffff
idtr:base=0x1c8, limit=0x7ff
dr0:0x0
dr1:0x0
dr2:0x0
dr3:0x0
dr6:0xffff0ff0
dr7:0x400
tr3:0x0
tr4:0x0
tr5:0x0
tr6:0x0
tr7:0x0
cr0:0x60000011
cr1:0x0
cr2:0x0
cr3:0x0
cr4:0x0
inhibit_mask:0
done
<bochs:41> u /10
00000141: ( ): pop ds ; 1f
00000142: ( ): iret ; cf
00000143: ( ): push gs ; 0fa8
00000145: ( ): push ebx ; 53
00000146: ( ): mov ebx, 0x18 ; bb18000000
0000014b: ( ): opsize mov gs, bx ; 668eeb
0000014e: ( ): opsize mov bx, word ptr [ds:0x55] ; 668b1d55
0000
00000155: ( ): shl ebx, 1 ; d1e3
00000157: ( ): gs mov al, byte ptr gs:[ebx] ; 658803
0000015a: ( ): shr ebx, 1 ; d1eb
<bochs:42> step
Next at t=16156850
(0) [0x000000d1] 0008:000000d1 (unk. ctxt): push eax ; 50
<bochs:43> info registers
eax 0x41 65
ecx 0x80 128
edx 0x40 64
ebx 0x0 0
esp 0xc28 0xc28
ebp 0x0 0x0
esi 0x5c8 1480
edi 0x9c8 2504
eip 0xd1 0xd1
eflags 0x83 131
cs 0x8 8
ss 0x10 16
ds 0x10 16
es 0x0 0
fs 0x0 0
gs 0x0 0
<bochs:44> |
|