我一直在搞砸一个多阶段引导加载程序,我已经让我的所有代码都可以工作,除了最后一部分:跳跃。我之前已经解决了这段代码,但我想通过替换这一行来使其更加模块化:
jmp 0x7E0:0
有了这个:
jmp far [Stage2Read + SectorReadParam.bufoff]
与其硬编码代码将加载到何处,我想间接跳转到它。这是我的其余代码:
; This is stage 1 of a multi-stage bootloader
bits 16
org 0x7C00
jmp 0:boot_main
%include "io16.inc"
boot_main:
; setup the new stack
cli
mov ax, 0x100
mov ss, ax
mov bp, 0x4000
mov sp, bp
sti
; Setup data segment
xor ax, ax
mov ds, ax
; Save which drive we booted from
mov [Stage2Read + SectorReadParam.drive], dl
; Home-made BIOS wrapper to read sectors into memory
mov si, Stage2Read
call ReadSectors
; Change to new data segment
mov ax, [Stage2Read + SectorReadParam.bufseg]
mov ds, ax
;jmp 0x7E0:0 ; THIS WORKS
jmp far [Stage2Read + SectorReadParam.bufoff] ; BUT THIS DOES NOT
; Used as the parameters for ReadSectors
Stage2Read: ISTRUC SectorReadParam
AT SectorReadParam.bufoff, dd 0
AT SectorReadParam.bufseg, dw 0x07E0
AT SectorReadParam.numsecs, db 1
AT SectorReadParam.track, db 0
AT SectorReadParam.sector, db 2
AT SectorReadParam.head, db 0
AT SectorReadParam.drive, db 0 ; needs to be initialized!
IEND
; Ending
times 510-($-$$) db 0
dw 0xAA55
请记住,所有这些代码都已经过测试并且可以正常工作,除了间接的远跳工作。这就是我让这个工作所需要的一切。我想知道间接远跳是否隐含地使用了例如ds
,以便地址Stage2Read + SectorReadParam.bufoff
不正确。这真的很困扰我,因为它看起来很简单。我想要帮助!
你的原始代码中有几个错误。首先,您使用DD(32位DWORD)而不是16位WORD进行偏移。这一行:
AT SectorReadParam.bufoff, dd 0
应该是:
AT SectorReadParam.bufoff, dw 0
默认情况下(在本例中)为 FAR JMP 指定内存操作数时,该操作数相对于 DS(数据段)。在 FAR JMP 之前,您将 DS 设置为新值,因此 JMP 内存操作数将从错误的段(0x07e0 而不是 0x0000)读取内存地址。
您可以在 JMP 后设置 DS,也可以使用覆盖将内存操作数更改为相对于 CS(仍然是包含数据的段)。它可能看起来像这样:
jmp far [CS:Stage2Read + SectorReadParam.bufoff]
你期望jmp far
从Stage2Read + SectorReadParam.bufoff
读取它的目标地址,这基本上是0x0000:Stage2Read + SectorReadParam.bufoff
(ds
= 0x0000)。
但是,就在跳转之前,ds
设置为0x07e0,因此在我看来,您的代码正在从0x07e0:Stage2Read + SectorReadParam.bufoff
读取其目标地址。