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

Bootloader从puts32_done返回后异常跳转到putsc16问题求助

问题:从puts32_done返回后意外跳转到putsc16

执行流程异常截图

我完全搞不懂为什么程序从puts32_done返回后会跳转到putsc16,已经深入排查过但毫无头绪,求技术指导。


相关代码片段

进入保护模式的核心代码

movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0 # 现在进入保护模式

# 远跳转到stage2
ljmpl $CODE_SEG32, $pmode_entry

.code32
.align 4
pmode_entry:
cli # 进入保护模式前务必关闭中断,避免三重故障
movw $DATA_SEG32, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %fs
movw %ax, %gs
movw %ax, %ss

# 设置栈(确保该区域可写)

# 调试:直接写入视频内存
movl $0x0f, %eax  # 黑底白字的'PP'
movl $0xb8000, %edi
movl %eax, (%edi)

32位字符串打印函数

puts32:
pushl %ebp
movl %esp, %ebp
pushl %ebx
movl 8(%ebp), %ebx  # 从栈中获取字符串地址
movl $0xb8000, %edx # 视频内存地址
movb $0x0f, %ah     # 黑底白字属性
puts32_loop:
movb (%ebx), %al
testb %al, %al
jz puts32_done
movw %ax, (%edx)
addl $1, %ebx
addl $2, %edx
jmp puts32_loop
puts32_done:
popl %ebx
leave
ret

排查方向

  • 未初始化栈指针:进入保护模式后仅设置了ss段寄存器,但未初始化esp。调用puts32时的栈操作会使用随机内存地址,导致返回地址被破坏,最终跳转到错误位置。解决:在pmode_entry中添加栈指针初始化,比如movl $0x7c00, %esp(选择安全、未占用的内存区域作为栈顶)。
  • 段描述符配置错误:CODE_SEG32或DATA_SEG32的GDT描述符基址、限长或属性配置错误,导致32位模式下内存寻址偏差,返回地址被解析为putsc16的地址。解决:检查GDT中32位段的配置,确保覆盖的内存区域正确。
  • 链接或对齐问题:编译链接时32位代码段与16位代码段未正确分隔,或代码对齐不足,导致栈中返回地址因溢出被覆盖。解决:检查链接脚本的段布局,确保32位与16位代码段分离,编译时启用正确的对齐选项(如.align 4)。
  • 中断时机错误:原代码在进入保护模式后才执行cli,切换CR0过程中可能触发未处理的中断或异常,导致流程跳转。解决:在实模式下先执行cli,再修改CR0进入保护模式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 14:52:33