我正在尝试在 AMD 286 系统上使用异常处理来初始化保护模式。我已经在 Bochs 上调试了下面的代码,它在那里运行良好。在 Pentium 4 机器上运行时也是如此。但是在 286 上,当它到达int3
指令时,它只会出现三倍错误。可观察到的行为是:如果我注释掉int3
,我会无限期地在屏幕上显示“OK”,而在代码原样的情况下,系统会重新启动。
该代码将由FASM 编译,并将二进制文件放入HDD 或FDD 的引导扇区。我实际上是从 1.4M 软盘上运行它的。
org 0x7c00
use16
CODE_SELECTOR = code_descr - gdt
DATA_SELECTOR = data_descr - gdt
; print "OK" on the screen to see that we've actually started
push 0xb800
pop es
xor di,di
mov ax, 0x0700+'O'
stosw
mov ax, 0x0700+'K'
stosw
; clear the rest of the screen
mov cx, 80*25*2-2
mov ax, 0x0720
rep stosw
lgdt [cs:gdtr]
cli
smsw ax
or al, 1
lmsw ax
jmp CODE_SELECTOR:enterPM
enterPM:
lidt [idtr]
mov cx, DATA_SELECTOR
mov es, cx
mov ss, cx
mov ds, cx
int3 ; cause an exception
jmp $
intHandler:
jmp $
gdt:
dq 0
data_descr:
dw 0xffff ; limit
dw 0x0000 ; base 15:0
db 0x00 ; base 23:16
db 10010011b ; present, ring0, non-system, data, extending upwards, writable, accessed
dw 0 ; reserved on 286
code_descr:
dw 0xffff ; limit
dw 0x0000 ; base 15:0
db 0x00 ; base 23:16
db 10011011b ; present, ring0, non-system, code, non-conforming, readable, accessed
dw 0 ; reserved on 286
gdtr:
dw gdtr-gdt-1
gdtBase:
dd gdt
idt:
rept 14
{
dw intHandler
dw CODE_SELECTOR
db 0
db 11100111b ; present, ring3, system, 16-bit trap gate
dw 0 ; reserved on 286
}
idtr:
dw idtr-idt-1
idtBase:
dd idt
finish:
db (0x7dfe-finish) dup(0)
dw 0xaa55
我想我正在使用 286 不支持的一些 CPU 功能,但究竟是什么以及在哪里?