286不能从保护模式切换回实模式,MSW寄存器有明确的说明,lmsw指令也明确说明不能将PE位置0.
从保护模式切回实模式只能通过reset,IBM搞得办法的是通过8042复位80286。
286复位之后CPU的状态:
MSW(Machine Status Word)
;
;masm 6.0
;
.286p
sseg segment use16 stack
db 4096 dup (0)
sseg ends
dseg segment use16
gdt dq 0
dq 00009a000000ffffh ;8
dq 000092000000ffffh ;0x10
dq 00009a000000ffffh
dq 000092000000ffffh ;0x20
dq 0000920b80007fffh ;0x28
dq 000092000000ffffh ;0x30
dq 0
dq 0
dq 0
gdtr dw gdtr - gdt -1
dd 0
idtr dw 256*8 - 1
dd 0
real_idt:
dw 03ffh
dd 0
io21 db 0
ioa1 db 0
dseg ends
cseg segment use16
assume cs:cseg,ds:dseg,ss:sseg
start:
mov ax,dseg
mov ds,ax
mov dx,16
mul dx
mov word ptr [gdtr +2 ],ax
mov byte ptr [gdtr +4],dl
;
mov word ptr [gdt + 10h + 2],ax
mov byte ptr [gdt + 10h + 4],dl
mov ax,cseg
mov dx,16
mul dx
mov word ptr [gdt + 8 + 2],ax
mov byte ptr [gdt + 8 + 4],dl
mov ax,sseg
mov ss,ax
mov sp,4096
mov dx,16
mul dx
mov word ptr [gdt + 20h + 2],ax
mov byte ptr [gdt + 20h + 4],dl
cli
lgdt fword ptr [gdtr]
smsw ax
or al,1
lmsw ax
db 0eah
dw offset prot16
dw 8
prot16:
mov ax,10h
mov ds,ax
mov ax,20h
mov ss,ax
mov sp,4096
mov ax,28h
mov es,ax
smsw ax
mov di,160*9
call hexasc
in al,021h
mov io21,al
in al,0a1h
mov ioa1,al
mov ax,30h
mov ds,ax
mov es,ax
mov bx,467h
mov ax,offset r_dos
mov [bx],ax
mov ax,seg cseg
mov [bx +2],ax
;
;CMOS寄存器0xF用于记录BIOS Shutdown Status Byte, 这个字节范围是0-0xa,用于索引
;在IBM AT BIOS CODE中的跳转表。
;
mov al,0fh
out 70h,al
mov al,05h
out 71h,al
mov al,0feh
out 64h,al
jmp $
r_dos:
mov ax,dseg
mov ds,ax
;复位CPU后BIOS将SS:SP设置成0x30:0x100
;这里尽快设置SS:SP以免破坏BIOS数据
mov ax,sseg
mov ss,ax
mov sp,4096
mov al,[ioa1]
out 0a1h,al
mov al,[io21]
out 21h,al
sti
mov ah,4ch
int 21h
hexasc:
push ax
shr ax,8
call hex8
pop ax
hex8:
push ax
shr al,4
call hex81
pop ax
hex81:
and al,0fh
add al,30h
cmp al,39h
jbe hex82
add al,7h
hex82:
mov ah,2
stosw
ret
cseg ends
end start