如何修复“从引导加载程序跳转到C代码时出现的无限循环错误”

时间:2019-01-03 04:30:47

标签: c operating-system masm bootloader

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

尽管我的引导程序正常工作,但是当引导程序跳转到以a.COM程序用C编写的内核代码时,问题仍然存在。最主要的是,尽管伪代码只能运行一次,但伪代码只是不断地反复打印字符。好像一次又一次地调用主代码。这是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

1 个答案:

答案 0 :(得分:1)

仔细查看start的结尾。

从未调用

start -直接跳转到它,并设置堆栈本身。当_BootMain返回时,堆栈为空;否则,堆栈为空。 ret末尾的start将从堆栈末尾弹出垃圾数据,并尝试跳转到该数据。如果该内存包含零,程序流将返回到main

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

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