【发布时间】:2015-08-13 09:38:28
【问题描述】:
这是演示操作系统内核基本功能的代码的一部分。
刷新 GTD 并设置 IDT 后,我想切换到 ring 3 运行一些 int 和上下文切换。
但是我无法跳转到用户模式。我想在iret 指令中使用技巧。据我所知iret 会弹出
从堆栈以下值:SS ESP EFLAGS CS EIP 所以想法是将正确的值推送到堆栈(使用新的段选择器),
并让iret 在寄存器中设置值。这是我正在使用的代码:
.equ NULL_DESCRIPTOR, 0x0000000000000000
.equ CODE_P3, 0x40C3FA000000D090
.equ DATA_P3, 0x40C3F2000000D090
.equ CODE_KERNEL, 0x00CF9A000000FFFF
.equ DATA_KERNEL, 0x00CF92000000FFFF
GDT:
.quad NULL_DESCRIPTOR
.quad CODE_P3 #0x08
.quad DATA_P3 #0x10
.quad CODE_KERNEL #0x18
.quad DATA_KERNEL #0x20
_GDT:
.word 39
.long GDT
.global flushGDT
.type flushGDT, @function
flushGDT:
cli
lgdt _GDT
xor %eax, %eax
#Data segment setup
mov $0x10, %ax
mov %ax, %ds
mov %ax, %gs
mov %ax, %fs
mov %ax, %es
#Stack save
mov %esp, %eax
#stack setup for iret and user space return
pushl $0x10
pushl %eax
pushf
#enable ints after switch to ring 3
pop %eax
or $0x200, %eax
push %eax
#CS selector
pushl $0x08
pushl $0x60 #Address of .leave (I have written proper ld script and checked with objdump)
iret
.section .upper_code, "ax", @progbits
.leave:
hlt
call upperKernelCode
问题在于iret 在开始对选择器的权限级别执行此指令检查并执行代码后,导致 CPU 故障并重置。
这是 BOCHS 的日志表:check_cs(0x0008): non-conforming code seg descriptor dpl != cpl, dpl=3, cpl=0。我将非常感谢有关此问题的任何帮助
【问题讨论】:
标签: assembly x86 operating-system kernel