【问题标题】:How to fix " Infinite Loop error on jumping to C code from bootloader"如何修复“从引导加载程序跳转到 C 代码时出现无限循环错误”
【发布时间】:2019-01-03 04:30:47
【问题描述】:

我实际上是在尝试运行 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

【问题讨论】:

    标签: c operating-system masm bootloader


    【解决方案1】:

    仔细看看start的结尾。

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-18
      • 1970-01-01
      • 2020-07-10
      • 2020-01-30
      • 1970-01-01
      • 1970-01-01
      • 2020-04-09
      • 2012-03-29
      相关资源
      最近更新 更多