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