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
相关产品推荐
相关产品推荐

