x86 NASM 间接远距离跳跃在真实模式下



我一直在搞砸一个多阶段引导加载程序,我已经让我的所有代码都可以工作,除了最后一部分:跳跃。我之前已经解决了这段代码,但我想通过替换这一行来使其更加模块化:

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 farStage2Read + SectorReadParam.bufoff读取它的目标地址,这基本上是0x0000:Stage2Read + SectorReadParam.bufoffds = 0x0000)。

但是,就在跳转之前,ds设置为0x07e0,因此在我看来,您的代码正在从0x07e0:Stage2Read + SectorReadParam.bufoff读取其目标地址。

最新更新