【发布时间】:2016-11-06 19:51:52
【问题描述】:
我是操作系统开发的新手,我很好奇我在开发自己的引导加载程序时遇到的问题。我的操作系统将用汇编语言编写,并将在 16 位实模式下运行。
我知道堆栈是什么,并且我的印象是它向下增长到内存中。如果我弄错了,请纠正我。我知道如何将基本内核从软盘加载到内存中,但我认为这不是问题所在。
我遇到的问题是我不确定在哪里放置堆栈并将我的内核加载到内存中。我试过像这样创建我的堆栈,但遇到了问题:
mov ax, 0x0000
mov ss, ax
mov sp, 0xFFFF
我正在0x1000:0x0000 加载我的内核。当我在我的print 函数中PUSH 和后来POP 易失性寄存器时,我的内核只是在我执行call print 的秒 时间挂起。这是我的print 函数:
print:
push ax
push bx
push cx
mov al, [si]
cmp al, 0
je p_Done
cmp al, 9
je p_Tab
mov ah, 0xE
int 0x10
cmp al, 10
je p_NewLine
p_Return:
inc si
jmp print
p_Tab:
xor cx, cx
p_Tab_Repeat:
cmp cx, 8
je p_Return
mov ah, 0xE
mov al, " "
int 0x10
inc cx
jmp p_Tab_Repeat
p_NewLine:
xor bx, bx
mov ah, 0x3
int 0x10
mov dl, 0x00
mov ah, 0x2
int 0x10
jmp p_Return
p_Done:
pop cx
pop bx
pop ax
ret
这些是我想要显示的行:
db "Kernel successfully loaded!", 10, 0
db 9, "Lmao, just a tab test!", 10, 0
这是我的内核运行时得到的输出(_ 是光标):
Kernel successfully loaded!
_
它成功打印了第一行,但在打印第二行时挂起。如果我删除 PUSH 和 POP 语句,它就可以正常工作。当我尝试在print 函数中保存和恢复寄存器时,为什么我的内核会挂起?我应该在哪里放置我的堆栈以及我应该在哪里加载我的内核?
【问题讨论】:
-
您未对齐堆栈。您应该将 SP 设置为 0。这会将第一个压入堆栈的单词放在 0000:FFFE。但这不是你的问题,这可能在于你没有显示的代码。您的代码应该与初始化为 0000:FFFF 的 SS:SP 和 1000:0000 的代码一起使用。
-
你确定你只需要一个堆栈吗?一旦您开始研究多任务处理,您将需要“更多”。
-
@Ross Ridge 哦。单词被压入堆栈?不是字节?我觉得这是我应该知道的,但感谢您让我意识到这一点。
-
@tofro 我现在正在制作一个单任务内核。
-
在 16 位模式下,推送和弹出是字大小的(即 16 位)。基本上,推送旨在推送寄存器的内容,因此推送/弹出与寄存器具有相同的大小。背景信息在这里:stackoverflow.com/a/15855444/366904
标签: assembly stack x86-16 osdev real-mode