【问题标题】:x86 NASM Indirect Far Jump In Real Mode实模式下的 x86 NASM 间接远跳
【发布时间】:2016-08-15 11:30:05
【问题描述】:

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

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 将不正确。这真的让我很烦,因为它看起来很简单。我需要帮助!

【问题讨论】:

  • 也许我看错了,但你有 AT SectorReadParam.bufoff, dd 0 。即 DD(32 位值)设置为零。在我看来jmp far dword [Stage2Read + SectorReadParam.bufoff] 会跳转到 0x0000:0x0000?
  • @MichaelPetch 哎呀,这是一个错误,但仍然无法正常工作......
  • 我已将 DD / DW 错误放回您的问题中,以保持我上面写的原始 cmets 的相关性。

标签: assembly x86 nasm x86-16 bootloader


【解决方案1】:

您的原始代码中有几个错误。第一个事实是您使用 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]

【讨论】:

  • 所以它确实使用了隐式寄存器...谢谢!
【解决方案2】:

您期望jmp farStage2Read + SectorReadParam.bufoff 读取其目标地址,这实际上是0x0000:Stage2Read + SectorReadParam.bufoff (ds = 0x0000)。

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

【讨论】:

    猜你喜欢
    • 2013-02-21
    • 2015-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-06-18
    • 2013-07-21
    相关资源
    最近更新 更多