陈贱伟 发表于 2013-8-29 23:22:25

从实模式到保护模式出现错误

org 07c00h
jmp main
gdt_null:
dd 0
dd 0
gdt_code_addr equ $ - gdt_null ; 求得代码段在GDT表中的位置
gdt_code:
dw 0ffffh ; 段大小为4GB
dw 0 ; 基地址(24位)
db 0
db 10011010b ; 属性描述位,指明此是代码段,可读可执行
db 11001111b ; 具体的每一位是代表什么可查Intel CPU编程手册
db 0
gdt_data_addr equ $ - gdt_null ; 求得数据段在GDT表中的位置
gdt_data:
dw 0ffffh
dw 0
db 0
db 10010010b ; 指明此是数据段,可读可写
db 11001111b
db 0
gdt_addr:
dw gdt_addr - gdt_null - 1 ; GDT 表的大小
dd gdt_null ; GDT 表的位置
; ---------------------------------------------------------------------------

main: ; 引导程序从此处开始执行
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0100h

lgdt ; 载入 GDT 的描述符
;关中断
cli
;打开地址A20
in al,92h
or al,00000010b
out 92h,al

mov eax , cr0 ; 下面三句设置 cr0 的第 0 位(PE位)为1,
; 表示进入保护模式
or eax , 1
mov cr0 , eax
jmp gdt_code_addr:code_32 ; 跳入32位的代码段中

code_32:
mov ax , gdt_data_addr ; 以下三句设置 DS,ES,SS,FS,GS
; 为数据段描述表的位置


times 510-($-$$) db 0
dw 0xaa55;结束标志
哪里错了

小名明SIU 发表于 2013-8-29 23:22:26

上面是我在你的基础上改的,说实话,不建议把段的描述符直接定义在数据中,应该自己写个子过程,在里面计算描述符,这样代码可读性强点。不好意思,上次看错代码了。你的代码段选择子放的位置是对的,不过还是不建议你这样写,应该在代码中计算出来,因为是ring0级的所以没问题,如果是用户层ring3的就有问题了

LinuxDeepin 发表于 2013-8-29 23:59:06

实在是太高深了,我还没有学到这一步,正在实验七中徘徊,帮你顶了

菜鸟的春天 发表于 2013-8-30 17:00:59

还没能开明白

小名明SIU 发表于 2013-8-30 23:59:33

本帖最后由 小名明SIU 于 2013-9-3 13:12 编辑

对你的代码只有一个评价:乱。
这些问题调试一下就知道了。
dw gdt_addr - gdt_null - 1 ; GDT 表的大小
错了,应该是dw gdt_addr - gdt_null,不要减一,不信找个特殊的减减试试。

陈贱伟 发表于 2013-8-31 17:16:52

小名明SIU 发表于 2013-8-30 23:59 static/image/common/back.gif
对你的代码只有一个评价:乱。
这些问题调试一下就知道了。
dw gdt_addr - gdt_null - 1 ; GDT 表的大小...

还是不明白能不能告诉我放在哪个位置

小名明SIU 发表于 2013-8-31 23:45:48

放在第一个描述符和第二个描述符之间

小名明SIU 发表于 2013-8-31 23:47:46

我劝你还是学会怎么调试吧

小名明SIU 发表于 2013-9-1 11:39:19

觉得好就采纳一下啊

陈贱伟 发表于 2013-9-2 21:18:37

小名明SIU 发表于 2013-9-1 11:39 static/image/common/back.gif
觉得好就采纳一下啊

{:5_100:}能不能把代码修改后 给我

小名明SIU 发表于 2013-9-3 13:11:25

org 07c00h
jmp main
gdt_null:
dd 0
dd 0
gdt_code_addr equ $ - gdt_null ; 求得代码段在GDT表中的位置
gdt_code:
dw 0ffffh ; 段大小为4GB
dw 0 ; 基地址(24位)
db 0
db 10011010b ; 属性描述位,指明此是代码段,可读可执行
db 11001111b ; 具体的每一位是代表什么可查Intel CPU编程手册
db 0
gdt_data_addr equ $ - gdt_null ; 求得数据段在GDT表中的位置
gdt_data:
dw 0ffffh
dw 0
db 0
db 10010010b ; 指明此是数据段,可读可写
db 11001111b
db 0
gdt_addr:
dw gdt_addr - gdt_null; GDT 表的大小
dd gdt_null ; GDT 表的位置
; ---------------------------------------------------------------------------

main: ; 引导程序从此处开始执行
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov sp,0100h

lgdt ; 载入 GDT 的描述符
;关中断
cli
;打开地址A20
in al,92h
or al,00000010b
out 92h,al

mov eax , cr0 ; 下面三句设置 cr0 的第 0 位(PE位)为1,
; 表示进入保护模式
or eax , 1
mov cr0 , eax
jmp gdt_code_addr:code_32 ; 跳入32位的代码段中

code_32:
mov ax , gdt_data_addr ; 以下三句设置 DS,ES,SS,FS,GS
; 为数据段描述表的位置


times 510-($-$$) db 0
dw 0xaa55;结束标志

小名明SIU 发表于 2013-9-3 13:22:59

本帖最后由 小名明SIU 于 2021-3-22 18:48 编辑

如果不知道怎么调试,或者想学习一些保护模式的知识,虽然我知道的也不多,但是我会尽量帮你解答,还是推荐使用《X86从实模式到保护模式》
页: [1]
查看完整版本: 从实模式到保护模式出现错误