为什么这些实模式代码可以在虚拟机上运行,​​而在我的真机上不运行?

soc*_*ser 2 x86 assembly mbr x86-64 real-mode

我正在尝试将汇编代码写入 mbr 以使用 BIOS ISR。我将以下代码写入 mbr,希望在屏幕上打印字符“ABCD”:

mov ah,0x0e
mov bp,0x8000
mov sp,bp

push 'A' 
push 'B'
push 'C'
push 'D'

mov al, [0x7ffe]
int 0x10

mov al, [0x7ffc]
int 0x10

mov al, [0x7ffa]
int 0x10

mov al, [0x7ff8]
int 0x10

; infinite loop
jmp $

; padding 0s and set the  magic number to make it bootable
times 510 -( $ - $$ ) db 0     
dw 0xaa55
Run Code Online (Sandbox Code Playgroud)

这些代码在 bochs 或 qemu 模拟器上运行良好,但是当我写入我的真实磁盘并使用它来引导时,没有打印任何内容。我已经测试过将 %al 寄存器直接设置为 chars ,并且打印效果很好。我使用的是 AMD PhenomII 955 处理器,我做错了什么?

Mar*_*oom 5

用类似的东西初始化段寄存器

xor ax, ax       ;Initialize seg regs with 0
mov ss, ax 
mov ds, ax 
Run Code Online (Sandbox Code Playgroud)

指令mov al, [...]使用dswhilepush ...使用ss.
确保它们相等。


我没有提到它,但正如Michael正确指出的那样,更新SS.
这对SS:SP必须相对于中断自动更新,否则在初始化中途触发的中断将使用SS:SP不完全有效的对。

最简单的方法是在初始化sp 之后更新ss

mov bp, 0x8000
mov ss, ax
mov sp, bp
Run Code Online (Sandbox Code Playgroud)

因为 CPU 在mov ss, ....
否则,您可以将初始化代码显式包装cli sti成对。

  • 由于 OP 没有明确禁用中断(理论上 BIOS 可以在跳转到引导扇区代码之前让它们保持打开状态),您认为在不更改 _SP_ 的情况下更新 _SS_ 是否明智?我可能只是明确表示,如果更新 _SS:SP_ 则更新 _SS_ 然后更新 _SP_(更新到 _SS_ 并且中断在以下指令结束之前关闭)或者只是使用 _CLI_ 来关闭它们启动代码的持续时间。 (2认同)