LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 3125|回复: 3

【求助】bochs虚拟,代码跑飞了

[复制链接]
发表于 2009-4-23 20:48:55 | 显示全部楼层 |阅读模式
自己写了一个保护模式的程序,有两个任务,分别切换,但是每次系统调用返回的时候,代码就跑飞,大家帮忙看看。

程序如下:
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>
发表于 2009-4-26 21:19:41 | 显示全部楼层
把你编译的过程 输出信息发过来。越详细越好。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-4-27 19:10:10 | 显示全部楼层
编译过程:
as86 -0 -a -o boot.o boot.s
ld86 -0 -s -o boot boot.o
gas -o head.o head.s
gld -s -x -M head.o -o system > system.map

dd bs=32 if=boot of=Image skip=1
dd bs=512 if=system of=Image skip=2 seek=1

dd bs=8192 if=Image of=/dev/fd1

fd1就是个虚拟的B盘,完了以后,在以B盘作为启动盘 ,进行启动
回复 支持 反对

使用道具 举报

发表于 2009-6-24 21:36:41 | 显示全部楼层
哈哈,我也是一样的问题,每次iret切换至任务0时就会触发ignore int,导致输出一个C.
正在找原因,楼主的ID比较熟悉。。。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表