MASM:强制OFFSET指令不被重新定位

时间:2018-04-12 12:37:22

标签: assembly dos masm

我正在用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
    ...

我把&#34; BAD&#34;在引号中因为MASM实际上是正确的,因为bootseg也是cseg组的一部分(因为boot_data它是从其他一些段引用的),所以链接器标记&#34; real_start&#34;可重新定位。

所以问题是:如何告诉汇编程序我希望real_startbootseg本身出发?{/ p>

我尝试了一些有用的技巧,比如让bootseg成为第一个定义的段,或者使它成为段落对齐的,但这些对我来说似乎有些笨拙。

我还尝试将bootseg排除在cseg组之外,但我再次需要在引导扇区写入磁盘之前从其他段引用boot_data

1 个答案:

答案 0 :(得分:2)

您可以通过在符号前添加LEFT JOIN前缀来指定您希望OFFSET成为相对的段。例如:

segment:

然而,这不起作用,因为您使用了BYTE对齐,因此该段有两个不同的起始地址。在实模式中,段必须是段落(16字节)对齐,因此链接器将开始 mov ax, offset bootseg:real_start 向下舍入到最近的段落边界,然后将任何偏移调整为相对于新的起始地址。因为实际加载bootseg并执行它实际上启动了段落边界,这意味着所有调整后的偏移都是不正确的。

请注意,并不仅限于OFFSET指令,而且bootsegbootseg内的地址也有任何绝对引用。您应该考虑将bootseg PARA对齐。

如果您仍想使用字节对齐,则需要自己计算偏移量:

bootseg

请注意,由于您定位的是80286处理器,因此您可以这样做:

     mov     ax, real_start - boot_start

使用80186将PUSH立即指令引入x86架构。

如果您在 push real_start - boot_start 中有绝对引用:

bootseg

您需要将其更改为类似的内容,以便在执行引导扇区时纠正偏移:

mov  al, [boot_data.foo]

最后,您可以直接在MASM中避免整个PUSH / RETF废话和代码an absolute far JMP to a fixed segment,如下所示:

mov  al, BYTE PTR ds:[boot_data.foo - boot_start]