正如@Jester 提到的,我必须归零DS
with:
@@ -4,2 +4,4 @@ _start:
cli
+ xor %ax, %ax
+ mov %ax, %ds
mov $msg, %si
请注意,这是不可能的mov
立即到ds
: 我们必须经过ax
: 8086-为什么我们不能将立即数移入段寄存器? https://stackoverflow.com/questions/19074666/8086-why-cant-we-move-an-immediate-data-into-segment-register
所以问题的根源在于QEMU的初始状态和真实硬件的初始状态之间的差异。
我现在将以下 16 位初始化代码添加到我的所有引导加载程序中,以保证更干净的初始状态。正如迈克尔·佩奇在评论中提到的那样,并非所有这些都是强制性的。
.code16
cli
/* This sets %cs to 0. TODO Is that really needed? */
ljmp $0, $1f
1:
xor %ax, %ax
/* We must zero %ds for any data access. */
mov %ax, %ds
/* The other segments are not mandatory. TODO source */
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
/*
TODO What to move into BP and SP? https://stackoverflow.com/questions/10598802/which-value-should-be-used-for-sp-for-booting-process
Setting BP does not seem mandatory for BIOS.
*/
mov %ax, %bp
/* Automatically disables interrupts until the end of the next instruction. */
mov %ax, %ss
/* We should set SP because BIOS calls may depend on that. TODO confirm. */
mov %bp, %sp
我还发现了这个密切相关的问题:C 内核 - 在虚拟机上运行良好,但在实际计算机上运行不佳? https://stackoverflow.com/questions/30549526/c-kernel-works-fine-on-vm-but-not-actual-computer
The 英特尔手册第 3 卷系统编程指南 - 325384-056US 2015 年 9 月 https://web.archive.org/web/20151025081259/http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-system-programming-manual-325384.pdf9.10.2“STARTUP.ASM 列表
”包含一个大型初始化示例。