【发布时间】:2018-04-12 12:37:21
【问题描述】:
我正在用 MASM for DOS 编写一个多模块组装项目。特别是,我正在尝试做一个非常简单的类似DOS的操作系统,
我有几个这样定义的段;
fileseg segment byte public 'code'
fileseg ends
memseg segment byte public 'code'
memseg ends
diskseg segment byte public 'code'
diskseg ends
bootseg segment byte public 'code'
bootseg ends
如您所见,它们都是字节对齐的(设计决策)。我还有一个包含上述所有部分的 cseg 组
cseg group fileseg, memseg, diskseg, bootseg, ...
所以当我想引用公共标签时,无论它是否在不同的段中定义,我都会这样做:
assume ds:cseg, es:cseg, ss:cseg
mov si, offset label_in_this_segment
mov bx, offset label_in_another_segment
它会在 cseg 中获得“全局”偏移量,这是正确的。但是当你编写一些需要在固定位置执行的代码时,问题就出现了,作为引导扇区,在 0000:7C00h 执行(在我的例子中是 07C0:0)
所以我是这样写的:
bootseg segment byte public 'code'
; Want all data references to be relative to this segment, not CSEG
assume ds:bootseg
boot_start::
jmp start
boot_data t_bootloader_data <>
start:
; make IP point to 0000h
mov ax, 07C0h
push ax
mov ax, offset ds:real_start ; "BAD" offset
push ax
retf
real_start:
mov ax, cs
mov ds, ax
...
我把“BAD”放在引号中是因为 MASM 实际上做得对,因为 bootseg 也是 cseg 组的一部分(因为 boot_data 它是从其他一些段引用的),所以链接器将“real_start”标记为可重定位。
所以问题是:我如何告诉汇编程序我希望real_start 与bootseg 本身相抵消?
我尝试了一些有效的技巧,例如将 bootseg 设为定义的第一个片段,或使其与段落对齐,但这些对我来说似乎有些不合时宜。
我还尝试将 bootseg 排除在 cseg 组之外,但同样,在将引导扇区写入磁盘之前,我需要从其他段引用 boot_data。
【问题讨论】:
-
问题:bootseg 有两个值:开机时和跳远后。你可以做一个偏移差异。 (这在两个 cs 上都是有效且相同的)并使用这样的值。
-
不要试图让 MASM 了解偏移量。如果这是正确的语法,也许可以做类似
jmp 07C0h:(real_start - start)的事情(而不是那种 push/push / retf 的东西。IDK 如果你在达到real_start后不打算利用仍然在 AX 中的价值,为什么要使用 AX .) -
@PeterCordes 它是为 .286 编译的,所以既不能写 jmp XXXX:XXXX 也不能推送立即值。
-
@Trap 80286 肯定有
jmp far ptr16:16指令。是的,您可以使用它。 -
如果它解决了您的实际问题,请不要仔细研究您的问题,直接答案是使用
OFFSET bootseg:real_start。至于如何让 MASM 生成到特定固定段和偏移量的远跳转,请参阅这个问题:stackoverflow.com/questions/32706833/…