为何无法成功调用x86架构中的Call Gate?
问题分析与解决
你的代码存在两个核心问题,直接导致了Bochs中的错误:
- 错误将代码段描述符当作调用门使用:
call 0b10_0_00:0中的选择符0x10指向的是GDT里的普通代码段描述符,但callf指令通过调用门跳转时,选择符必须指向调用门描述符(系统段描述符的一种),而非普通代码段。 - 调用门结构缺失:你未按照调用门的专属格式定义GDT条目,当前第三个GDT条目是代码段格式,不符合调用门的结构要求。
修正后的引导扇区代码
boot equ 0x7C00 lgdt [boot + gdt_info] mov eax, cr0 or eax, 1 mov cr0, eax ; 调用调用门,选择符0x10指向GDT中的调用门描述符 call 0x10:0 gdt: ; 空描述符 dd 0, 0 ; 目标代码段描述符(选择符0x08):基址0x7C00,限长512字节,DPL=0的16位代码段 dd 0x7C0001FF, 0b00000000000000001_00_1101000000000 ; 调用门描述符(选择符0x10):目标选择符0x08,偏移0,无参数传递 dw 0x0000, 0x0008 ; 目标偏移低16位、目标代码段选择符 db 0x00, 0b11001110 ; 参数个数0、类型0xE(16位调用门)、DPL=0、存在位P=1 dw 0x0000 ; 16位模式下目标偏移高16位无用,设为0 gdt_info: dw 0x17 ; GDT总长度24字节,limit为总长度减一(24-1=23=0x17) dd boot + gdt times (510 - ($ - $$)) db 0 db 0x55, 0xAA
关键修正点说明
- 调用门格式:16位调用门的类型字段固定为
0xE,需设置存在位P=1、特权级DPL=0(与当前CPL一致),目标选择符指向你要跳转的代码段(0x08)。 - 指令调用对象:
call 0x10:0中的0x10现在正确指向调用门描述符,CPU会自动解析调用门并跳转到目标代码段的0偏移处。 - GDT长度验证:三个描述符共24字节,
gdt_info中的dw 0x17是正确的总长度减一,避免越界访问错误。
原错误解释
bx_dbg_read_pmode_descriptor: selector 0x0010 points to a system descriptor and is not supported!:CPU尝试将普通代码段描述符当作系统段(调用门)解析,格式不匹配导致报错。fetch_raw_descriptor: GDT: index (1007) 200 > limit (17):错误的调用门结构导致CPU计算出非法的GDT索引,触发越界访问异常。
内容的提问来源于stack exchange,提问作者Weg Wang
相关产品推荐
相关产品推荐

