Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly MASM:不重新定位的强制偏移指令_Assembly_Dos_Masm - Fatal编程技术网

Assembly MASM:不重新定位的强制偏移指令

Assembly MASM:不重新定位的强制偏移指令,assembly,dos,masm,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' boots

我正在用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
    ...
bootseg segment byte public 'code'

assume ds:bootseg

boot_start::

    jmp     start

    ; ...

start:

    jmp     real_start_abs
real_start:        
    mov     ax, cs
    mov     ds, ax

    ; ...

bootseg ENDS

bootseg_abs SEGMENT USE16 AT 07c0h
    ORG      (real_start - boot_start)
real_start_abs LABEL FAR
bootseg_abs ENDS
bootseg段字节公共“代码”
; 希望所有数据引用都与此段相关,而不是CSEG
假设ds:bootseg
启动启动::
jmp启动
启动数据启动加载程序启动数据
开始:
; 使IP指向0000h
mov ax,07C0h
推斧
mov ax,offset ds:real_start;“坏”偏移量
推斧
翻新
真正的开始:
mov-ax,cs
mov-ds,ax
...
我在引号中加上“BAD”,因为MASM实际上做得很好,因为bootseg也是
cseg
组的一部分(因为
boot_data
它是从一些其他段引用的),所以链接器将“real_start”标记为可重定位的

所以问题是:我如何告诉汇编程序我希望
real\u start
bootseg
本身相抵消

我尝试了一些有效的技巧,比如让
bootseg
成为定义的第一个段,或者让它与段落对齐,但这些对我来说似乎有点不太对劲


我还试图将
bootseg
从cseg组中移出,但在将引导扇区写入磁盘之前,我需要从其他段引用
boot\u数据。

您可以通过在符号前面加
段:
来指定要偏移的相对段。例如:

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

请注意,它不仅限于OFFSET指令,还包括对
bootseg
中地址的任何绝对引用。你应该考虑制作<代码> BooTeSG < /代码> PARA对齐。

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

     mov     ax, real_start - boot_start
请注意,由于您的目标是80286处理器,因此可以改为:

     push    real_start - boot_start
PUSH immediate指令是通过80186引入x86体系结构的

如果在
bootseg
中有这样的绝对引用:

mov  al, [boot_data.foo]
在执行引导扇区时,您需要将其更改为这样的值,以使偏移量正确:

mov  al, BYTE PTR ds:[boot_data.foo - boot_start]
最后,您可以避免整个PUSH/RETF无意义,直接在MASM中编写如下代码:

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
    ...
bootseg segment byte public 'code'

assume ds:bootseg

boot_start::

    jmp     start

    ; ...

start:

    jmp     real_start_abs
real_start:        
    mov     ax, cs
    mov     ds, ax

    ; ...

bootseg ENDS

bootseg_abs SEGMENT USE16 AT 07c0h
    ORG      (real_start - boot_start)
real_start_abs LABEL FAR
bootseg_abs ENDS

通过在符号前面加上
段:
,可以指定要偏移的相对段。例如:

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

请注意,它不仅限于OFFSET指令,还包括对
bootseg
中地址的任何绝对引用。你应该考虑制作<代码> BooTeSG < /代码> PARA对齐。

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

     mov     ax, real_start - boot_start
请注意,由于您的目标是80286处理器,因此可以改为:

     push    real_start - boot_start
PUSH immediate指令是通过80186引入x86体系结构的

如果在
bootseg
中有这样的绝对引用:

mov  al, [boot_data.foo]
在执行引导扇区时,您需要将其更改为这样的值,以使偏移量正确:

mov  al, BYTE PTR ds:[boot_data.foo - boot_start]
最后,您可以避免整个PUSH/RETF无意义,直接在MASM中编写如下代码:

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
    ...
bootseg segment byte public 'code'

assume ds:bootseg

boot_start::

    jmp     start

    ; ...

start:

    jmp     real_start_abs
real_start:        
    mov     ax, cs
    mov     ds, ax

    ; ...

bootseg ENDS

bootseg_abs SEGMENT USE16 AT 07c0h
    ORG      (real_start - boot_start)
real_start_abs LABEL FAR
bootseg_abs ENDS

问题是:bootseg有两个值:启动时和跳远后。你可以做一个补偿差。(在两个cs上都有效且相同)并使用该值。不要试图让MASM了解偏移量。如果这是正确的语法(而不是push/push/retf的东西,那么可以做一些类似于
jmp 07C0h:(real\u start-start)
的事情。IDK如果在到达
real\u start
后不打算利用AX中仍然存在的值,那么为什么要使用AX呢@彼得命令它是为.286编译的,因此既不能写入jmp XXXX:XXXX,也不能推送立即数。@Trap 80286最肯定的是
jmp far ptr16:16
指令。是的,你可以使用它。如果你的问题解决了你的实际问题,不用仔细研究,直接的答案是使用
OFFSET bootseg:real\u start
。至于如何让MASM生成到特定固定段和偏移量的跳远,请参见以下问题:问题:bootseg有两个值:启动时和跳远后。你可以做一个补偿差。(在两个cs上都有效且相同)并使用该值。不要试图让MASM了解偏移量。也许可以做一些类似于
jmp 07C0h:(rea