我实际上正在尝试运行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
答案 0 :(得分:1)
仔细查看start
的结尾。
start
-直接跳转到它,并设置堆栈本身。当_BootMain
返回时,堆栈为空;否则,堆栈为空。 ret
末尾的start
将从堆栈末尾弹出垃圾数据,并尝试跳转到该数据。如果该内存包含零,程序流将返回到main
。
您需要设置在_BootMain
返回之后要发生的特定操作。如果只想在执行_BootMain
之后挂起系统,请在jmp .
的末尾插入一个无限循环(例如start
),而不是错误的ret
。
或者,考虑让引导加载程序自行设置堆栈,并设置call
COM可执行文件。当返回时,引导加载程序可以采取适当的措施。