Assembly 在启用中断之前,使用中断门将其延迟。一旦进入保护模式,您就不能进行DOS或BIOS调用。我的代码只是执行HLT,将受保护模式代码置于不执行任何操作的等待状态。正如prl指出的,如果您不首先清除EDX,您的DIV指令可能会失败并溢出。由于您的IDT中没有定义

Assembly 在启用中断之前,使用中断门将其延迟。一旦进入保护模式,您就不能进行DOS或BIOS调用。我的代码只是执行HLT,将受保护模式代码置于不执行任何操作的等待状态。正如prl指出的,如果您不首先清除EDX,您的DIV指令可能会失败并溢出。由于您的IDT中没有定义,assembly,x86,operating-system,masm,protected-mode,Assembly,X86,Operating System,Masm,Protected Mode,在启用中断之前,使用中断门将其延迟。一旦进入保护模式,您就不能进行DOS或BIOS调用。我的代码只是执行HLT,将受保护模式代码置于不执行任何操作的等待状态。正如prl指出的,如果您不首先清除EDX,您的DIV指令可能会失败并溢出。由于您的IDT中没有定义中断门(包括处理除法异常的中断门),故障将崩溃@PeterCordes:这实际上不是一个重复。即使他有一个#DE处理器,这段代码仍然会失败,因为IDT没有从正确的内存地址加载。GDT也没有正确加载,代码也没有像OP所说的那样正确进入32位保护模


在启用中断之前,使用中断门将其延迟。一旦进入保护模式,您就不能进行DOS或BIOS调用。我的代码只是执行HLT,将受保护模式代码置于不执行任何操作的等待状态。正如prl指出的,如果您不首先清除EDX,您的
DIV
指令可能会失败并溢出。由于您的IDT中没有定义中断门(包括处理除法异常的中断门),故障将崩溃@PeterCordes:这实际上不是一个重复。即使他有一个#DE处理器,这段代码仍然会失败,因为IDT没有从正确的内存地址加载。GDT也没有正确加载,代码也没有像OP所说的那样正确进入32位保护模式。他只使其达到准16位保护模式。在编写可能位于任意段的DOS EXE(不是COM或bootloaders))程序和线性地址问题时,这个问题是有效的。我投票重新打开它,因为我可以提供一个合理的answer@MichaelPetch:是的,只涵盖了显示错误配置IDT的内容。切换后尝试对机器进行任何其他操作都会很快导致类似的问题。作为#DE的复制品结束并不是解决这个问题的最有用的方法,因为这样做是一个有用的问答库。
.386p

GDT struct
limit_0_15 word ?
base_0_15  word ?
base_16_23 byte ?
access_byt byte ?
fl_limit   byte ?
base_24_31 byte ?
GDT ends

main_data segment use16
idt_start:
    db 800h dup (?)
idt_info:
    dw 2048
    dd idt_start

gdt_start:
nul_gdt GDT <0,0,0,0,0,0>
c32_gdt GDT <0,0,0,0,0,0>
d32_gdt GDT <0,0,0,0,0,0>
gdt_info:
    dw gdt_info - gdt_start - 1
    dd gdt_start

main_data ends

main_code segment use16
assume cs:main_code, ds:main_data, ss:stack16
_start:

mov  ax,main_data
mov  ds,ax
mov  ax,code16
mov  es,ax
call es:[Check_A20]
call es:[Set_A20]
call es:[Check_A20]
call es:[Create_GDT]

mov  bx,gdt_info
lgdt fword ptr[bx]

mov  bx,idt_info
lidt fword ptr[bx]

mov  eax,cr0
or   eax,1
mov  cr0,eax

jmp clear_prefetch_queue
nop
nop
clear_prefetch_queue:

mov  eax,0ffffh
mov  ebx,0fh
div  ebx

exit:
mov  ah,4ch
int  21h
main_code ends



code16 segment use16

Wait_8042_command proc ; wait for the kbd controller to get ready to take in commands
in   al,64h
test al,2
jnz  Wait_8042_command
ret
Wait_8042_command endp

Wait_8042_data proc   ; wait for the kbd controller to get ready to take in data
in   al,64h
test al,1
jz   Wait_8042_data
ret
Wait_8042_data endp

Check_A20 proc
pushf
push ds
push es
push di
push si

cli
xor  ax,ax
mov  es,ax
mov  di,500h
not  ax
mov  ds,ax
mov  si,510h

mov  al,byte ptr es:[di]
push ax
mov  al,byte ptr ds:[si]
push ax

mov  byte ptr es:[di],0
mov  byte ptr ds:[si],0ffh
cmp  byte ptr es:[di],0ffh

pop  ax
mov  byte ptr ds:[si],al
pop  ax
mov  byte ptr es:[di],al

mov  ax,0
je   check_a20_exit
mov  ax,1

check_a20_exit:
pop  si
pop  di
pop  es
pop  ds
popf
retf
Check_A20 endp

Set_A20 proc
cli
call Wait_8042_command
mov  al,0ADh             ;set command to disable kbd
out  64h,al

call Wait_8042_command
mov  al,0d0h
out  64h,al              ;read from input

call Wait_8042_data
in   al,60h              ;read input from kbd
push ax

call Wait_8042_command
mov  al,0d1h             ;write to output
out  64h,al

call Wait_8042_command
pop  ax
or   al,2
out  60h,al

call Wait_8042_command
mov  al,0AEh            ;enable kbd controller
out  64h,al

call Wait_8042_command
sti
retf
Set_A20 endp

Create_GDT proc
push ds
mov  ax,main_data
mov  ds,ax

;NULL Descriptor
;mov  cx,4
;rep  stosw
;code32 gdt initialized
mov  c32_gdt.limit_0_15, 0ffffh
mov  c32_gdt.base_0_15,  0h
mov  c32_gdt.base_16_23, 0h
mov  c32_gdt.access_byt, 9ah
mov  c32_gdt.fl_limit,   0cfh
mov  c32_gdt.base_24_31, 0h
;data32 gdt initialized
mov  d32_gdt.limit_0_15, 0ffffh
mov  d32_gdt.base_0_15,  0h
mov  d32_gdt.base_16_23, 0h
mov  d32_gdt.access_byt, 92h
mov  d32_gdt.fl_limit,   0cfh
mov  d32_gdt.base_24_31, 0h

pop  ds
retf
Create_GDT endp


code16 ends


code32 segment use32
mov  eax,0ffffh ;test garbage
mov  ebx,0fh
div  ebx
code32 ends

data32 segment use32

data32 ends


stack16 segment stack use16
    dw 200h dup (?)
stack16 ends

end _start