Assembly 实模式下的x86 NASM间接跳远
我一直在摆弄一个多级引导加载程序,我所有的代码都可以工作,除了最后一部分:跳转。我以前已经编写过这段代码,但我想通过替换这一行使其更加模块化:Assembly 实模式下的x86 NASM间接跳远,assembly,x86,nasm,x86-16,bootloader,Assembly,X86,Nasm,X86 16,Bootloader,我一直在摆弄一个多级引导加载程序,我所有的代码都可以工作,除了最后一部分:跳转。我以前已经编写过这段代码,但我想通过替换这一行使其更加模块化: jmp 0x7E0:0 关于这一点: jmp far [Stage2Read + SectorReadParam.bufoff] 我想做一个间接的跳转到它,而不是硬编码,代码将加载到其中。以下是我的其余代码: ; This is stage 1 of a multi-stage bootloader bits 16
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
就不正确了。这真的让我很烦,因为它看起来很简单。我想要帮助 您希望jmp far
从Stage2Read+SectorReadParam.bufoff
读取其目标地址,这实际上是0x0000:Stage2Read+SectorReadParam.bufoff
(ds
=0x0000)
但是,就在跳转之前,
ds
被设置为0x07e0,因此在我看来,您的代码正在从0x07e0:Stage2Read+SectorReadParam.bufoff
读取其目标地址。您的原始代码中有几个错误。第一个事实是,偏移量使用DD(32位DWORD)而不是16位字。这一行:
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]
也许我看错了,但您在SectorReadParam.bufoff,dd 0上有
。即DD(32位值)设置为零。在我看来,jmp far-dword[Stage2Read+SectorReadParam.bufoff]
将跳转到0x0000:0x0000?@MichaelPetch-Oops是的,这是一个bug,但仍然不起作用……我已经将DD/DW bug放回你的问题中,以保持我上面写的原始注释的相关性。因此它确实使用了一个隐式寄存器。。。谢谢