You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何IA-32保护模式下Pagefault Interrupt不能使用RET指令?

问题

我正在学习IA-32保护模式下的IDT表,已创建IDT描述符并触发Pagefault Interrupt(0xe),程序运行正常。但在int 0xe的处理代码中添加RET指令后,VMware虚拟机出现“VMware Workstation unrecoverable error: (vcpu-0)”错误。Pagefault等价于int 0xe软中断,单独调用int 0xe无异常,为何无法用RET指令返回至原执行代码?

相关代码

org 0x7c00

flatcode equ 0x0008
flatdata equ 0x0010
flatstack equ 0x0010


section .text

[bits 16]

bsp16:

    cli

    xor ax,ax
    mov ds,ax

    lgdt [GDT_DESC]
    lidt [IDT_DESC]

    mov ax,0
    mov ds,ax
    mov es,ax
    mov si,pagedir      
    mov di,00001000h
    mov cx,pagedir_end - pagedir        
    cld     
    rep movsb

    mov ax,0
    mov ds,ax
    mov es,ax
    mov si,page_l2_0        
    mov di,00002000h
    mov cx,page_l2_end - page_l2_0      
    cld     
    rep movsb

    mov ax,0
    mov ds,ax
    mov es,ax
    mov si,int0             ;transport int 0
    mov di,0000a000h
    mov cx,int0_end - int0      
    cld     
    rep movsb

    mov ax,0
    mov ds,ax
    mov es,ax
    mov si,int0xe               ;transport int 0xe
    mov di,0000b000h
    mov cx,int0xe_end - int0xe      
    cld     
    rep movsb

    in al,92h
    or al,00000010b
    out 92h,al

    mov eax,00001000h
    mov cr3,eax

    mov eax,80000001h
    mov cr0,eax

    jmp dword flatcode:bsp32

[bits 32]

bsp32:

    mov ax,flatstack
    mov ss,ax
    mov esp,0x2fff

    int 0h                    ;int 0x0

    mov byte [0x6000],'a'     ;pagefault interrupt!

halt:mov byte [0xa00],'r'
    mov byte [0xa02],'e'
    mov byte [0xa04],'t'

    hlt

int0:

    mov ax,flatdata
    mov ds,ax

    mov byte [0xa0],'I'
    mov byte [0xa2],'n'
    mov byte [0xa4],'t'
    mov byte [0xa6],' '
    mov byte [0xa8],'0'

    ret

int0_end:

int0xe:

    mov ax,flatdata
    mov ds,ax

    mov byte [0x0],'P'
    mov byte [0x1],0fh
    mov byte [0x2],'a'
    mov byte [0x3],0fh
    mov byte [0x4],'g'
    mov byte [0x5],0fh
    mov byte [0x6],'e'
    mov byte [0x7],0fh
    mov byte [0x8],'F'
    mov byte [0xa],'a'
    mov byte [0xc],'u'
    mov byte [0xe],'l'
    mov byte [0x10],'t'

    ;jmp dword flatcode:halt  ---> OK
    ret                       ---> problem

int0xe_end:

pagedir:

    dd 00002001h            ;page-directory-table

pagedir_end:

page_l2_0:

    dd 000b8001h            ;text mode 80x25

page_l2_1:

    dd 0000a001h            ;int 0h

page_l2_2:

    dd 0000f001h            ;stack

page_l2_3:

    dd 0000b001h            ;int 0xe

page_l2_4:

    dd 00000000h

page_l2_5:

    dd 00000000h

page_l2_6:

    dd 00000000h

page_l2_7:

    dd 00007001h            ;bsp32

page_l2_end:

GDT:

    dq 0000000000000000h

GDT_CODE:

    dq 00cf9a000000ffffh

GDT_DATA:

    dq 00cf92000000ffffh

GDT_END:

GDT_DESC:

    dw GDT_END - GDT - 1        ;GDTR register value 32(addr)+16(limit)
    dd GDT

IDT:

    dq 00008e0000081000h        ;Interrupt discriptor table
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 0h                       ;idt-discriptor stored a selector and a offset address.
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 0h
    dq 00008e0000083000h        ;int 0xe

IDT_END:

IDT_DESC:

    dw IDT_END - IDT - 1            ;IDTR register value 32(addr)+16(limit)
    dd IDT

times 510 - ($ - $$) db 0

db 0x55
db 0xaa
解答

核心问题是硬件异常(如页错误)和软中断int 0xe的栈帧结构完全不同,直接用ret会导致栈指针失衡,破坏系统运行状态。

1. 两种场景的栈帧差异

  • 软中断int 0xe:执行该指令时,CPU仅向栈中压入三个值:EFLAGS(4字节)、CS(4字节)、EIP(4字节),总栈帧大小12字节。此时ret指令可以正确弹出这三个值,完成返回(因为int在这里的行为类似带特权检查的call,ret正好匹配call的栈操作)。
  • 页错误(硬件触发的0xe异常):当CPU检测到页错误时,除了压入EFLAGS、CS、EIP,还会额外压入一个4字节的错误码,总栈帧大小16字节。此时用ret指令只能弹出12字节,栈指针ESP会停留在错误码的位置,后续代码会使用错误的栈数据,直接导致栈混乱,触发虚拟机崩溃。

2. 代码问题点

  • 单独调用int 0xe属于软中断场景,栈帧符合ret的要求,所以能正常返回;
  • 访问[0x6000]触发页错误时,CPU自动压入错误码,栈帧多了4字节,ret无法正确处理这个额外的栈数据,直接引发系统异常。

3. 正确的返回方式

硬件异常处理程序必须使用iret指令返回,而非ret。对于带错误码的异常(如页错误),需要先手动弹出错误码,再执行iret:

int0xe:
    mov ax,flatdata
    mov ds,ax

    ; 页错误处理逻辑...

    add esp,4        ; 弹出额外的错误码
    iret             ; 用iret恢复EIP、CS、EFLAGS并返回

iret指令会严格按照硬件异常的栈帧结构恢复执行环境,而ret只适用于函数调用或不带错误码的软中断返回。


内容的提问来源于stack exchange,提问作者sanzenyou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 03:45:56