x86 NASM实模式下的间接跳远 [英] x86 NASM Indirect Far Jump In Real Mode
问题描述
我一直在搞一个多阶段的引导程序,除了后半段 Jump 之外,我所有的代码都可以使用.我之前已经获得了这段代码,但是我想通过替换以下行使其更加模块化:
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
有了这个:
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
请记住,所有这些代码均已通过测试并且可以工作,但间接远跳除外.这就是我要做的一切.我想知道间接远跳是否隐式使用了例如 ds
,这样地址 Stage2Read + SectorReadParam.bufoff
会是不正确的.这真的让我烦恼,因为它是如此简单.我需要帮助!
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!
推荐答案
您的原始代码中有几个错误.首先是使用 DD (32位 DWORD )而不是16位 WORD 的偏移量.这行:
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
应该是:
AT SectorReadParam.bufoff, dw 0
默认情况下(对于您的情况)为 FAR JMP 指定内存操作数时,它相对于 DS (数据段).在 FAR JMP 之前,将 DS 设置为新值,因此 JMP 内存操作数将从错误的段中读取内存地址(取而代之的是0x07e0为0x0000).
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).
您可以在 JMP 之后设置 DS ,也可以将内存操作数更改为相对于 CS 的内存(仍然是段使用数据).看起来可能像这样:
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]
这篇关于x86 NASM实模式下的间接跳远的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!