首页 > 解决方案 > 如何修复“从引导加载程序跳转到 C 代码时出现无限循环错误”

问题描述

我实际上是在尝试运行 C 代码来编写我的操作系统内核来研究操作系统是如何工作的。当引导加载程序跳转到我的 C 代码时,我陷入了这个无限循环。我应该如何防止这个错误

尽管我的引导加载程序工作正常,但当我的引导加载程序跳转到用 C 作为a.COM程序编写的内核代码时,问题就出现了。主要的是,尽管代码只能运行一次,但虚拟代码只是不断地一次又一次地打印一个字符。似乎主代码被一次又一次地调用。这是程序startpoint.asm集头和bootmain.cpp文件的代码。


这是startpoint.asm最初链接时使用的代码,以便可以自动调用代码。(写在MASM中)

注意:代码是在地址加载的2000H:0000H

;------------------------------------------------------------
.286                 ; CPU type
;------------------------------------------------------------
.model TINY               ; memory of model
;---------------------- EXTERNS -----------------------------
extrn        _BootMain:near     ; prototype of C func
;------------------------------------------------------------
;------------------------------------------------------------   
.code   

main:
        jmp short start     ; go to main
        nop

;----------------------- CODE SEGMENT -----------------------
start:  
        cli
        mov ax,cs               ; Setup segment registers
        mov ds,ax               ; Make DS correct
        mov es,ax               ; Make ES correct
        mov ss,ax               ; Make SS correct        
        mov bp,2000h
        mov sp,2000h            ; Setup a stack
        sti
                                ; start the program 
        call           _BootMain
        ret

        END main                ; End of prog

代码bootmain.cpp

extern "C" void BootMain()
{
    __asm
    {
         mov ah,0EH
         mov al,'G'
         int 10H
    } 
    return;
}

编译和链接器命令如下:

编译代码bootmain.cpp

CL.EXE /AT /G2 /Gs /Gx /c /Zl bootmain.cpp

编译代码startpoint.asm

ML.EXE /AT /c startpoint.asm

将它们链接起来的代码(按保留顺序):

LINK.EXE /T /NOD startPoint.obj bootmain.obj

预期输出

G           

实际输出:

GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG

标签: coperating-systemmasmbootloader

解决方案


仔细看看结尾start

start永远不会被调用——它被直接跳转到,它自己设置堆栈。返回时_BootMain,栈为空;ret末尾的将从start堆栈末尾弹出垃圾数据并尝试跳转到它。如果该内存包含零,则程序流程将返回到main.

你需要设置一些特定的东西在_BootMain返回后发生。如果您只是希望系统在执行后挂起_BootMain,请插入一个无限循环(例如jmp .)到结尾start而不是错误的ret.

或者,考虑让您的引导加载程序设置堆栈本身和callCOM 可执行文件。当它返回时,引导加载程序可以采取适当的措施。


推荐阅读