程序集进入保护模式并跳回到实模式

问题描述 投票:1回答:1

我正在组装中开发玩具OS,从保护模式切换回实模式时遇到问题。我已经成功切换到保护模式,称为内核,该内核将文本写入[0xb8000]视频存储器,返回给调用者,并(可能)切换回实模式。我正在尝试使用实模式下的bios中断,因此不必编写自己的设备驱动程序。

但是,切换回实模式后似乎没有执行中断。它们不会像在保护模式下那样使系统崩溃,所以我想我处于实模式。

minrep.asm(引导加载程序)

boot.header:
[BITS 16]
[ORG 0x7c00]
mov ax, cs
mov ds, ax
xor ax, ax
mov ds, ax
cli
mov ss, ax
mov sp, 0x7c00
sti
call main
jmp $
disk.read_sectors:
reset:
xor ax,ax
int 0x13
jc reset
floppy:
xor bx,bx
mov ah,0x2
mov al, [esp+6]
mov cx,[esp+4]
mov dh,0x0
mov dl, 0x80
mov bx, ds
mov es, bx
mov bx, [esp+2]
int 0x13
jc error
mov ax, 0
ret
error:
mov ax, 1
ret
main:
push word 16 ; 16 sectors for stage2
push word 2 ; starts at sector 2
push word 0x1000 ; into 0x1000 memory buffer
call disk.read_sectors
pop bx
pop bx
pop bx
jmp 0000:0x1000
mov ax, 0
ret
footer:
times 510-($-boot.header) db 0
dw 0xAA55

minrep_st2.asm(stage2,输入prot并返回到实数)

[BITS 16]
[ORG 0x1000]

stage2.header:

mov ax, cs
mov ds, ax
jmp stage2.main

stage2.main:

mov al, 'B'
mov ah, 0x0E
mov bh, 0x00
mov bl, 0x07
int 0x10

call switch_to_protected
switch_to_protected:


            [ bits 16 ]

            cli

            switch_to_pm:

                lgdt [ gdt_descriptor ]
                mov eax , cr0
                or eax , 0x1
                mov cr0 , eax
                jmp CODE_SEG:init_pm

            [ bits 32 ]

            init_pm:

                   mov ax, DATA_SEG
                mov ds, ax
                mov ss, ax
                mov es, ax
                mov fs, ax
                mov gs, ax
                mov ebp , 0x90000
                mov esp , ebp

                sti






[BITS 32]
switch_to_real:


mov [0xb8000], byte 'D'

[BITS 32]
cli

mov eax, cr0
and eax, 0x7FFFFFFF    ; clear PG bit
mov cr0, eax

xor     eax,eax         ; A convenient zero
mov     cr3,eax         ; Flush the TLB

mov eax, cr0
and eax, 0xFFFFFFFE    ; clear PE bit
mov cr0, eax

lidt [idtr]

jmp 0:continue

[BITS 16]

continue:

sti

mov al, 'C'
mov ah, 0x0E
mov bh, 0x00
mov bl, 0x07
int 0x10

hlt


GDT:


            idtr:
            dw 0x3ff
            dd 0

            gdt_start:

                gdt_null:
                    dd 0x0 ;
                    dd 0x0

                gdt_code:
                    dw 0xffff
                    dw 0x0
                    db 0x0
                    db 10011010b ; 1 st flags , type flags
                    db 11001111b ; 2 nd flags , Limit ( bits 16 -19)
                    db 0x0

                gdt_data:
                    dw 0xffff
                    dw 0x0
                    db 0x0
                    db 10010010b ; 1 st flags , type flags
                    db 11001111b ; 2 nd flags , Limit ( bits 16 -19)
                    db 0x0

                gdt_end:

                gdt_descriptor:
                    dw gdt_end - gdt_start - 1
                    dd gdt_start

            CODE_SEG equ gdt_code - gdt_start
            DATA_SEG equ gdt_data - gdt_start

stage2.footer:
times 8192-($-stage2.header) db 0

如何编译:

nasm.bat minrep.asm -o disk_p1.bin
nasm minrep_st2.asm -o disk_p2.bin
copy /b disk_pt1.bin + disk_pt2.bin disk.img
call qemu disk.img

编辑:

如果我仅这样做是为了得到保护,那么在实模式下移动至0xb800确实会清除第一个字符,但不能正确打印它(空白字符而不是字节'Z')

        [ bits 16 ]

    cli

    switch_to_pm:

        lgdt [ gdt_descriptor ]
        mov eax , cr0
        or eax , 0x1
        mov cr0 , eax
        jmp CODE_SEG:init_pm

    [ bits 32 ]

    init_pm:

sti中的打印字符'Z'继续:

mov ax, 0xb800; 
mov es, ax; 
mov [es:0000], byte 'Z'
assembly kernel nasm x86-16 bootloader
1个回答
0
投票

我找到了解决问题的方法:http://www.rohitab.com/discuss/topic/35103-switch-between-real-mode-and-protected-mode/

查看Napalm的代码。它对我有用。

© www.soinside.com 2019 - 2024. All rights reserved.