x86 NASM间接远程跳转实模式

时间:2016-04-22 02:09:29

标签: assembly x86 nasm x86-16 real-mode

我一直在搞乱多阶段引导程序,除了最后一部分外,我已经完成了所有代码的工作: The Jump 。我之前已经解决了这个代码,但我想通过替换这一行来使其更加模块化:

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不正确。这真是让我烦恼,因为它看起来很简单。我想帮忙!

2 个答案:

答案 0 :(得分:1)

您希望jmp farStage2Read + SectorReadParam.bufoff读取目标地址,0x0000:Stage2Read + SectorReadParam.bufoffds = 0x0000)。

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

答案 1 :(得分:1)

您的原始代码中有几个错误。第一个是使用 DD (32位 DWORD )而不是16位 WORD 进行偏移的事实。这一行:

AT SectorReadParam.bufoff, dd 0

应该是:

AT SectorReadParam.bufoff, dw 0

默认情况下为 FAR JMP 指定内存操作数时(在您的情况下),它相对于 DS (数据段)。在 FAR JMP 之前,将 DS 设置为新值,因此 JMP 内存操作数将从错误的段读取内存地址(0x07e0而不是of 0x0000)。

您可以在 JMP 之后设置 DS ,或者您可以将内存操作数更改为相对于 CS (仍然是细分)使用数据)使用覆盖。它看起来像这样:

jmp far [CS:Stage2Read + SectorReadParam.bufoff]