加载全局描述符表会导致错误
我的引导加载程序上有一个子例程“ switch32”,应该将过渡到32位保护模式,但是lgdt
指令似乎会造成麻烦。这是代码 “ switch32.asm”:
gdt_start:
gdt_null:
dq 0x0
gdt_code:
dw 0xFFFF ;Lower 16 bits of limit
dw 0x0000 ;Lower 16 bits of base address
db 0x00 ;Middle 8 bits of base address
db 10011010b;Access byte: present=1,privilege=00,type=1,exec=1,comform=0,read=1,acc=0
db 0100111b ;High 4 bits = flags, Low 4 bits = last nibble of limit (20 bits)
db 0x00 ;Higher 8 bits of base address (32 bits)
gdt_data:
dw 0xFFFF ;Lower 16 bits of limit
dw 0x0000 ;Lower 16 bits of base address
db 0x00 ;Middle 8 bits of base address
db 10010010b;Access byte: present=1,privilege=00,type=1,exec=0,dir=0,write=1,acc=0
db 0100111b ;High 4 bits = flags, Low 4 bits = last nibble of limit (20 bits)
db 0x00 ;Higher 8 bits of base address (32 bits)
gdt_end:
gdtr_data: ;The data to pass to the GDTR register (lower word=size of GDT, higher dword=address of GDT)
dw gdt_end - gdt_start - 1 ;16 bit size of GDT
dd gdt_start ;Address to start of GDT
CODE_SEGMENT equ gdt_code - gdt_start ;Index of code segment descriptor
DATA_SEGMENT equ gdt_data - gdt_start ;Index of data segment descriptor
switch32:
pusha
cli ;Disable interrupts
lgdt [gdtr_data]
;Set first bit (protected mode enable) in control register 0
mov eax,cr0
or eax,0x1
mov cr0,eax
jmp CODE_SEGMENT:post_flush ; 'fake' far jump to trick CPU into flushing pipeline to prevent nasty exceptions
; according to intel manual, CS register is implicitly set to far JMP's selector
post_flush:
[bits 32]
mov eax,DATA_SEGMENT
mov ds,eax
mov ss,eax
mov es,eax
mov fs,eax
mov gs,eax
popa
ret
我正在使用qemu,每当调用子例程时,屏幕开始闪烁,没有任何超过lgdt
指令,我很确定这意味着有一个CPU错误。该错误来自lgdt
指令,但对于原因,我毫无意义。我是否将正确的数据传递给GDTR寄存器?还是我的整个GDT设置错误?
我正在将Intel I386程序员手册和全球描述符表中的Osdev Wiki文章用作资源,并且根据我阅读的内容设置了GDT。
I have a subroutine 'switch32' on my bootloader which is supposed to make the transition to 32 bit protected mode, however the lgdt
instruction seems to be causing trouble. Here is the code for
"switch32.asm":
gdt_start:
gdt_null:
dq 0x0
gdt_code:
dw 0xFFFF ;Lower 16 bits of limit
dw 0x0000 ;Lower 16 bits of base address
db 0x00 ;Middle 8 bits of base address
db 10011010b;Access byte: present=1,privilege=00,type=1,exec=1,comform=0,read=1,acc=0
db 0100111b ;High 4 bits = flags, Low 4 bits = last nibble of limit (20 bits)
db 0x00 ;Higher 8 bits of base address (32 bits)
gdt_data:
dw 0xFFFF ;Lower 16 bits of limit
dw 0x0000 ;Lower 16 bits of base address
db 0x00 ;Middle 8 bits of base address
db 10010010b;Access byte: present=1,privilege=00,type=1,exec=0,dir=0,write=1,acc=0
db 0100111b ;High 4 bits = flags, Low 4 bits = last nibble of limit (20 bits)
db 0x00 ;Higher 8 bits of base address (32 bits)
gdt_end:
gdtr_data: ;The data to pass to the GDTR register (lower word=size of GDT, higher dword=address of GDT)
dw gdt_end - gdt_start - 1 ;16 bit size of GDT
dd gdt_start ;Address to start of GDT
CODE_SEGMENT equ gdt_code - gdt_start ;Index of code segment descriptor
DATA_SEGMENT equ gdt_data - gdt_start ;Index of data segment descriptor
switch32:
pusha
cli ;Disable interrupts
lgdt [gdtr_data]
;Set first bit (protected mode enable) in control register 0
mov eax,cr0
or eax,0x1
mov cr0,eax
jmp CODE_SEGMENT:post_flush ; 'fake' far jump to trick CPU into flushing pipeline to prevent nasty exceptions
; according to intel manual, CS register is implicitly set to far JMP's selector
post_flush:
[bits 32]
mov eax,DATA_SEGMENT
mov ds,eax
mov ss,eax
mov es,eax
mov fs,eax
mov gs,eax
popa
ret
I'm using qemu and whenever the subroutine is called, the screen starts blinking and nothing past the lgdt
instruction is executed, I'm pretty sure that means there is a CPU error. The error is coming from the lgdt
instruction but i'm clueless as to why. Am I passing the right data to the GDTR register? or is my entire GDT set up wrong?
I'm using the intel i386 programmer manual and the osdev wiki article on the Global Descriptor Table as resources and I set up my GDT according to what I've read.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论