x86 NASM Indirect Far Jump In Real Mode

拈花ヽ惹草 提交于 2021-02-05 08:51:15

问题


I have been messing around with a multi-stage bootloader and I have got all of my code to work, except for the last part: The Jump. I have gotten this code to work out before now but I wanted to make it more modular by replacing this line:

jmp 0x7E0:0

With this one:

jmp far [Stage2Read + SectorReadParam.bufoff]

Instead of hard coding where the code will load in, I wanted to do an indirect jump to it. Here's the rest of my code:

; 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              

Remember all this code has been tested and works except for the indirect far jump to work. That's all I need to get this to work. I was wondering if maybe the indirect far jump implicitly is using for example ds so that the address Stage2Read + SectorReadParam.bufoff would be incorrect. This is really bugging me because it is so seemingly simple. I would like help!


回答1:


You had a couple of bugs in your original code. The first was the fact that you had the offset using a DD (32-bit DWORD) instead of a 16-bit WORD. This line:

AT SectorReadParam.bufoff, dd 0

Should have been:

AT SectorReadParam.bufoff, dw 0

When you specify the memory operand for the FAR JMP by default (in your case) it is relative to the DS (data segment). Before the FAR JMP you set DS to a new value, so the JMP memory operand will read the memory address from the wrong segment (0x07e0 instead of 0x0000).

You can either set DS after you JMP or you can change the memory operand to be relative to CS (which is still the segment with the data) using an override. It could look like this:

jmp far [CS:Stage2Read + SectorReadParam.bufoff]



回答2:


You're expecting jmp far to read its destination address from Stage2Read + SectorReadParam.bufoff, which is essentially 0x0000:Stage2Read + SectorReadParam.bufoff (ds = 0x0000).

However, just before the jump, ds is set to 0x07e0, so it seems to me that your code is reading its destination address from 0x07e0:Stage2Read + SectorReadParam.bufoff.



来源:https://stackoverflow.com/questions/36783568/x86-nasm-indirect-far-jump-in-real-mode

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!