引导加载程序引用数据和跳转

Bootloader referencing data and jumps

我正在尝试开发一个非常简单的引导加载程序,为此我正在关注 tutorial。我的问题是关于寻址和 org 命令。

我明白为什么需要 org 命令来获取给定地址的数据。由于引导扇区将加载到地址 0x7c00,因此需要通知编译器该地址应添加到任何引用中。例如,如果没有 [org 0x7c00] 命令,下面的代码将无法工作,因为它会在地址 0x0012 而不是 0x7c12.

处获取数据
[org 0x7c00]

; print String
mov ah, 0x0e
mov bx, text
printLoop:
    mov al,[bx]
    cmp al,0
    je loop
    int 0x10
    inc bx
    jmp printLoop

loop:
    jmp loop

text: ; at address 0x0012 in the file but will be loaded at 0x7c12
    db 'Loading OSiris operating system...',10,13,0

times 510-($-$$) db 0

dw 0xaa55

现在我不明白的是为什么jmp命令不一样?简而言之,我不明白为什么下面的代码有效(无限打印?,org command commented)。

;[org 0x7c00]

mov ah, 0x0e
mov al, '?'
loop: ; as I understood 0x0004 in the file but 0x7c04 in the memory
    int 0x10
    jmp loop ; hence this should jump at 0x0004 and the code should not work (but it actually works)

times 510-($-$$) db 0
dw 0xaa55

根据我的理解,应该跳转到地址 0x0004 。因此计算机应该无限启动而不只是打印“?”。与本地跳转和代码段有关吗?

这种形式的短 jmp 是使用相对偏移量编码的。它基本上说 "jump back 4 bytes"。因此,它与位置无关并且无论如何都可以工作。实际的机器码是EB FC,其中EB是短跳转的操作码,FC-4,从执行的后续指令的地址开始计算的偏移量正常继续。

另请注意,入口点只能保证在物理地址 0x7c00,您不应该依赖它 0:0x7c00。某些 BIOS 可能使用 0x7c0:0。为了安全起见,您应该初始化您的段寄存器,包括 CS(为此使用远跳转)。