YASM [symbol+$$] 平面二进制文件中的有效地址太复杂

YASM [symbol+$$] Effective Address is Too Complex in a flat binary

org 0x7c00 是在平面二进制文件中获取正确绝对地址的正常方法,但我很好奇我期望的另一种工作方式。

我尝试使用 section boot vstart=0x7c00 align=1 告诉 YASM 正确的内存地址,在另一个使用 start=300.

的部分使用 symbol
mov [symbol+$$], register

yasm -fbin boot.asm 在该行给出 error: effective address too complex

按我的理解,symbol+$$应该可以处理成数字(而不是段+偏移量)吧?如果我错了,请告诉我,但如果我是对的,那为什么 YASM 告诉我地址​​太复杂了?

是否有另一种方法可以使用 start= and/or vstart= 而不是 org 并仍然获得正确的绝对寻址?

使用[symbol]无效;汇编成 [0000]

的绝对地址

我之所以想这样做,是因为我有一个引导加载程序的二进制机器代码,它可以自行重定位,但它在重定位之前在某些符号中存储了一些值,(例如,引导驱动器在 dl)

中传递

YASM 支持带有 "sections" 的二进制程序,它可以有不同的寻址偏移量,所以我所做的是我设置了代码,其中 MBR 是第一个扇区的前 300 个字节,变量被存储在 300 个字节之后和第 446 个字节之前,我想使用这种方法,以便我可以使用技术上来自其他部分的变量,但相对于当前部分的偏移量进行复制。

这是我正在尝试做的事情的简化示例:

; example.asm
; yasm -fbin example.asm

%define virtual(_name, _offset) section _name vstart=_offset align=1
%define absolute(_name, _offset) section _name start=_offset align=1

virtual(boot, 0x7c00) ; Virtual Offset of 0x7c00 (in-file offset of 0)
start:
    ; This is just an example
    ; There isn't going to be much here.
    mov [boot_drive+$$], dl

    cli 
    hlt

absolute(vars, 300) ; Virtual AND in-file offset of 300

boot_drive db 0

YASM 似乎相当古怪,但是 NASM 在关键表达式中使用 $-$$ 时似乎更加理智(例如部分的 start 选项)。玩了一会儿,我有理由不使用 YASM。

如果您愿意使用 NASM,看来您可以使用它。我删除了宏以显示如何使用基本 section 指令完成它:

; example.asm
; nasm -fbin example.asm -o example.bin

BOOT_ORG       EQU 0x7c00
BOOT_RELOC_ORG EQU 0x0600

section unreloc start=0x0000 vstart=BOOT_ORG align=16
start:
    ; This is just an example
    ; There isn't going to be much here.
    mov [boot_drive], dl
    mov al, [partition_1]
    ; Do relocation code here

    jmp 0x0000:reloc_start

section reloc follows=unreloc vstart=BOOT_RELOC_ORG+($-$$) align=1
reloc_start:
    mov [boot_drive], dl
    mov al, [partition_1]
    cli
    hlt

section vars start=300 vstart=300+BOOT_ORG align=1
boot_drive db 0

section parttbl start=446 vstart=446+BOOT_ORG align=1
partition_1:
dq 0x80, 0
partition_2:
dq 0, 0
partition_3:
dq 0, 0
partition_4:
dq 0, 0

section bootsig start=510 vstart=510+BOOT_ORG align=1
dw 0xaa55

当我使用 ndisasm -b16 -o0x7c00 example.bin 时,我得到的输出似乎是正确的:

00007C00  88162C7D          mov [0x7d2c],dl
00007C04  A0BE7D            mov al,[0x7dbe]
00007C07  EA0C060000        jmp word 0x0:0x60c
00007C0C  88162C7D          mov [0x7d2c],dl
00007C10  A0BE7D            mov al,[0x7dbe]
00007C13  FA                cli
00007C14  F4                hlt
00007C15  0000              add [bx+si],al
00007C17  0000              add [bx+si],al
00007C19  0000              add [bx+si],al
00007C1B  0000              add [bx+si],al
00007C1D  0000              add [bx+si],al
00007C1F  0000              add [bx+si],al
00007C21  0000              add [bx+si],al
00007C23  0000              add [bx+si],al
00007C25  0000              add [bx+si],al
00007C27  0000              add [bx+si],al
00007C29  0000              add [bx+si],al
00007C2B  0000              add [bx+si],al
00007C2D  0000              add [bx+si],al
00007C2F  0000              add [bx+si],al
00007C31  0000              add [bx+si],al
00007C33  0000              add [bx+si],al
00007C35  0000              add [bx+si],al
00007C37  0000              add [bx+si],al
00007C39  0000              add [bx+si],al
00007C3B  0000              add [bx+si],al
00007C3D  0000              add [bx+si],al
00007C3F  0000              add [bx+si],al
00007C41  0000              add [bx+si],al
00007C43  0000              add [bx+si],al
00007C45  0000              add [bx+si],al
00007C47  0000              add [bx+si],al
00007C49  0000              add [bx+si],al
00007C4B  0000              add [bx+si],al
00007C4D  0000              add [bx+si],al
00007C4F  0000              add [bx+si],al
00007C51  0000              add [bx+si],al
00007C53  0000              add [bx+si],al
00007C55  0000              add [bx+si],al
00007C57  0000              add [bx+si],al
00007C59  0000              add [bx+si],al
00007C5B  0000              add [bx+si],al
00007C5D  0000              add [bx+si],al
00007C5F  0000              add [bx+si],al
00007C61  0000              add [bx+si],al
00007C63  0000              add [bx+si],al
00007C65  0000              add [bx+si],al
00007C67  0000              add [bx+si],al
00007C69  0000              add [bx+si],al
00007C6B  0000              add [bx+si],al
00007C6D  0000              add [bx+si],al
00007C6F  0000              add [bx+si],al
00007C71  0000              add [bx+si],al
00007C73  0000              add [bx+si],al
00007C75  0000              add [bx+si],al
00007C77  0000              add [bx+si],al
00007C79  0000              add [bx+si],al
00007C7B  0000              add [bx+si],al
00007C7D  0000              add [bx+si],al
00007C7F  0000              add [bx+si],al
00007C81  0000              add [bx+si],al
00007C83  0000              add [bx+si],al
00007C85  0000              add [bx+si],al
00007C87  0000              add [bx+si],al
00007C89  0000              add [bx+si],al
00007C8B  0000              add [bx+si],al
00007C8D  0000              add [bx+si],al
00007C8F  0000              add [bx+si],al
00007C91  0000              add [bx+si],al
00007C93  0000              add [bx+si],al
00007C95  0000              add [bx+si],al
00007C97  0000              add [bx+si],al
00007C99  0000              add [bx+si],al
00007C9B  0000              add [bx+si],al
00007C9D  0000              add [bx+si],al
00007C9F  0000              add [bx+si],al
00007CA1  0000              add [bx+si],al
00007CA3  0000              add [bx+si],al
00007CA5  0000              add [bx+si],al
00007CA7  0000              add [bx+si],al
00007CA9  0000              add [bx+si],al
00007CAB  0000              add [bx+si],al
00007CAD  0000              add [bx+si],al
00007CAF  0000              add [bx+si],al
00007CB1  0000              add [bx+si],al
00007CB3  0000              add [bx+si],al
00007CB5  0000              add [bx+si],al
00007CB7  0000              add [bx+si],al
00007CB9  0000              add [bx+si],al
00007CBB  0000              add [bx+si],al
00007CBD  0000              add [bx+si],al
00007CBF  0000              add [bx+si],al
00007CC1  0000              add [bx+si],al
00007CC3  0000              add [bx+si],al
00007CC5  0000              add [bx+si],al
00007CC7  0000              add [bx+si],al
00007CC9  0000              add [bx+si],al
00007CCB  0000              add [bx+si],al
00007CCD  0000              add [bx+si],al
00007CCF  0000              add [bx+si],al
00007CD1  0000              add [bx+si],al
00007CD3  0000              add [bx+si],al
00007CD5  0000              add [bx+si],al
00007CD7  0000              add [bx+si],al
00007CD9  0000              add [bx+si],al
00007CDB  0000              add [bx+si],al
00007CDD  0000              add [bx+si],al
00007CDF  0000              add [bx+si],al
00007CE1  0000              add [bx+si],al
00007CE3  0000              add [bx+si],al
00007CE5  0000              add [bx+si],al
00007CE7  0000              add [bx+si],al
00007CE9  0000              add [bx+si],al
00007CEB  0000              add [bx+si],al
00007CED  0000              add [bx+si],al
00007CEF  0000              add [bx+si],al
00007CF1  0000              add [bx+si],al
00007CF3  0000              add [bx+si],al
00007CF5  0000              add [bx+si],al
00007CF7  0000              add [bx+si],al
00007CF9  0000              add [bx+si],al
00007CFB  0000              add [bx+si],al
00007CFD  0000              add [bx+si],al
00007CFF  0000              add [bx+si],al
00007D01  0000              add [bx+si],al
00007D03  0000              add [bx+si],al
00007D05  0000              add [bx+si],al
00007D07  0000              add [bx+si],al
00007D09  0000              add [bx+si],al
00007D0B  0000              add [bx+si],al
00007D0D  0000              add [bx+si],al
00007D0F  0000              add [bx+si],al
00007D11  0000              add [bx+si],al
00007D13  0000              add [bx+si],al
00007D15  0000              add [bx+si],al
00007D17  0000              add [bx+si],al
00007D19  0000              add [bx+si],al
00007D1B  0000              add [bx+si],al
00007D1D  0000              add [bx+si],al
00007D1F  0000              add [bx+si],al
00007D21  0000              add [bx+si],al
00007D23  0000              add [bx+si],al
00007D25  0000              add [bx+si],al
00007D27  0000              add [bx+si],al
00007D29  0000              add [bx+si],al
00007D2B  0000              add [bx+si],al
00007D2D  0000              add [bx+si],al
00007D2F  0000              add [bx+si],al
00007D31  0000              add [bx+si],al
00007D33  0000              add [bx+si],al
00007D35  0000              add [bx+si],al
00007D37  0000              add [bx+si],al
00007D39  0000              add [bx+si],al
00007D3B  0000              add [bx+si],al
00007D3D  0000              add [bx+si],al
00007D3F  0000              add [bx+si],al
00007D41  0000              add [bx+si],al
00007D43  0000              add [bx+si],al
00007D45  0000              add [bx+si],al
00007D47  0000              add [bx+si],al
00007D49  0000              add [bx+si],al
00007D4B  0000              add [bx+si],al
00007D4D  0000              add [bx+si],al
00007D4F  0000              add [bx+si],al
00007D51  0000              add [bx+si],al
00007D53  0000              add [bx+si],al
00007D55  0000              add [bx+si],al
00007D57  0000              add [bx+si],al
00007D59  0000              add [bx+si],al
00007D5B  0000              add [bx+si],al
00007D5D  0000              add [bx+si],al
00007D5F  0000              add [bx+si],al
00007D61  0000              add [bx+si],al
00007D63  0000              add [bx+si],al
00007D65  0000              add [bx+si],al
00007D67  0000              add [bx+si],al
00007D69  0000              add [bx+si],al
00007D6B  0000              add [bx+si],al
00007D6D  0000              add [bx+si],al
00007D6F  0000              add [bx+si],al
00007D71  0000              add [bx+si],al
00007D73  0000              add [bx+si],al
00007D75  0000              add [bx+si],al
00007D77  0000              add [bx+si],al
00007D79  0000              add [bx+si],al
00007D7B  0000              add [bx+si],al
00007D7D  0000              add [bx+si],al
00007D7F  0000              add [bx+si],al
00007D81  0000              add [bx+si],al
00007D83  0000              add [bx+si],al
00007D85  0000              add [bx+si],al
00007D87  0000              add [bx+si],al
00007D89  0000              add [bx+si],al
00007D8B  0000              add [bx+si],al
00007D8D  0000              add [bx+si],al
00007D8F  0000              add [bx+si],al
00007D91  0000              add [bx+si],al
00007D93  0000              add [bx+si],al
00007D95  0000              add [bx+si],al
00007D97  0000              add [bx+si],al
00007D99  0000              add [bx+si],al
00007D9B  0000              add [bx+si],al
00007D9D  0000              add [bx+si],al
00007D9F  0000              add [bx+si],al
00007DA1  0000              add [bx+si],al
00007DA3  0000              add [bx+si],al
00007DA5  0000              add [bx+si],al
00007DA7  0000              add [bx+si],al
00007DA9  0000              add [bx+si],al
00007DAB  0000              add [bx+si],al
00007DAD  0000              add [bx+si],al
00007DAF  0000              add [bx+si],al
00007DB1  0000              add [bx+si],al
00007DB3  0000              add [bx+si],al
00007DB5  0000              add [bx+si],al
00007DB7  0000              add [bx+si],al
00007DB9  0000              add [bx+si],al
00007DBB  0000              add [bx+si],al
00007DBD  00800000          add [bx+si+0x0],al
00007DC1  0000              add [bx+si],al
00007DC3  0000              add [bx+si],al
00007DC5  0000              add [bx+si],al
00007DC7  0000              add [bx+si],al
00007DC9  0000              add [bx+si],al
00007DCB  0000              add [bx+si],al
00007DCD  0000              add [bx+si],al
00007DCF  0000              add [bx+si],al
00007DD1  0000              add [bx+si],al
00007DD3  0000              add [bx+si],al
00007DD5  0000              add [bx+si],al
00007DD7  0000              add [bx+si],al
00007DD9  0000              add [bx+si],al
00007DDB  0000              add [bx+si],al
00007DDD  0000              add [bx+si],al
00007DDF  0000              add [bx+si],al
00007DE1  0000              add [bx+si],al
00007DE3  0000              add [bx+si],al
00007DE5  0000              add [bx+si],al
00007DE7  0000              add [bx+si],al
00007DE9  0000              add [bx+si],al
00007DEB  0000              add [bx+si],al
00007DED  0000              add [bx+si],al
00007DEF  0000              add [bx+si],al
00007DF1  0000              add [bx+si],al
00007DF3  0000              add [bx+si],al
00007DF5  0000              add [bx+si],al
00007DF7  0000              add [bx+si],al
00007DF9  0000              add [bx+si],al
00007DFB  0000              add [bx+si],al
00007DFD  0055AA            add [di-0x56],dl

我个人不会使用这种方法,因为使用我在之前关于 的回答中讨论的方法可以更轻松地完成它,这与 Ross Ridge 对这个问题的回答非常相似。

你的基本问题是你实际上并没有将两个数字相加,而是将两个符号相加,而汇编程序通常不允许这样做。这是因为目标文件格式没有任何方法可以将添加两个符号表示为重定位,那是因为添加两个符号并没有多大意义。虽然在这种情况下您正在生成一个不支持重定位的二进制文件,因此汇编器可以发明自己的虚拟重定位来处理这个问题,但显然这在 YASM 中没有作为一般规则的例外实现。

为什么汇编程序不允许添加符号

在可能生成目标文件的一般情况下,添加两个符号没有意义的原因是符号不仅仅是数字。它们还引用一个部分,并且部分最终可以存在于内存中的任何位置。您的 [bootdrive + $$] 表达式表示将 bootdrive 的实际地址加载到内存中,并将其添加到当前部分开头的实际地址。当生成目标文件时,汇编程序不知道这些实际地址是什么,符号所属的部分可以放在任何地方。甚至链接器也可能不知道,如果它正在生成 relocatable executable,这将取决于操作系统加载 executable.

的位置

(这忽略了这样一个事实,即您已经告诉汇编器 bootdrive 应该被视为具有与汇编器本来认为的不同的实际地址。这也是您的汇编器没有的支持在通常情况下输出目标文件。)

二进制文件可能是个例外,但不是

现在,在生成二进制文件的情况下,不涉及链接器,因此 YASM 可以知道 bootdrive 的 "actual" 地址为 300,而 $$ 有一个0x7c00 的实际地址。但这将要求汇编器在评估有效地址时产生异常,它必须传播到生成二进制文件的后端。该异常尚未在您的汇编程序中实现,您可能很难说服 YASM(或 NASM)开发人员这样做。

你很难说服他们,因为即使是二进制文件,添加两个符号也没有意义,即使你可以。您的示例代码只能工作,因为 bootdrive 的地址不是它的实际地址。实际上,您向其添加 $$ 的原因是为了计算其实际地址。由于您的示例用例是人为的且不必要的,因此有更好的方法来编写一个重新定位的引导加载程序,它不能很好地说明为什么添加两个符号是有意义的。

可能没有直接的解决方法

至于解决方法,我真的想不出任何仍然涉及使用 bootloader$$ 的直接解决方案。当有人试图添加两个符号时,通常有一种方法可以将其重写为有效的形式,通常是减去两个符号。汇编程序支持减去同一部分中的两个符号,因为它从等式中删除了公共部分。例如,[foo + bar_begin - bar_end] 可以写成 [foo + (bar_begin - bar_end)]。但是,我不确定您可以从 bootloader$$ 中减去什么以从等式中删除它们的任何部分。

虽然我确定还有其他方法可以解决您的问题,但仍然可以让您使用您正在使用的部分指令完成您想要的事情,但我不会费心去弄清楚那可能是什么是。相反,我将建议您所说的您不想要的解决方法,如果不是为了您自己的利益,那么也是为了其他人可能会遇到类似情况 post 的利益。

我的解决方案,即使不是你想要的

我的解决方案是不使用段指令来解决引导扇区位于两个不同地址的问题。相反,您可以使用反映大部分代码在复制后所在位置的 ORG。需要在原始位置执行的少量代码可以很容易地与位置无关,因此不关心使用什么 ORG。

以下是自重定位MBR引导块的框架。为简洁起见,省略了实现 MBR 所需的大部分代码。

    BITS    16

RELOC_OFFSET EQU 0x600

    ORG RELOC_OFFSET

start:
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0x7c00

    mov di, RELOC_OFFSET
    mov si, 0x7c00
    mov cx, 512 / 2
    cld
    rep movsw
    jmp 0:relocated_entry

relocated_entry:
    mov [boot_drive], dl
    ; ...
    mov dl, [boot_drive]
    jmp 0:0x7c00

boot_drive DB   0

    TIMES   446 - ($ - $$) DB 0
partition_table:
    DB  0x80, 0x01, 0x00, 0x05, 0x17, 0x01, 0x03, 0x01, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
    ; ...

    TIMES   510 - ($ - $$) DB 0
    DB  0x55, 0xaa

这里的关键是 boot_drive 只有在代码被移动后才能访问。 无需提前保存 DL,因为初始代码不需要更改 DL。实际上,完全不需要保存 DL 是可能的,因为通常不需要在 MBR 引导扇区中修改 DL。 TIMES 指令用于确保分区 table 和幻数在它们需要的位置。

这是 objdump -D -b binary -m i8086 -M intel --adjust-vma=0x600 的输出:

 600:   31 c0                   xor    ax,ax
 602:   8e d8                   mov    ds,ax
 604:   8e c0                   mov    es,ax
 606:   8e d0                   mov    ss,ax
 608:   bc 00 7c                mov    sp,0x7c00
 60b:   bf 00 06                mov    di,0x600
 60e:   be 00 7c                mov    si,0x7c00
 611:   b9 00 01                mov    cx,0x100
 614:   fc                      cld    
 615:   f3 a5                   rep movs WORD PTR es:[di],WORD PTR ds:[si]
 617:   ea 1c 06 00 00          jmp    0x0:0x61c
 61c:   88 16 29 06             mov    BYTE PTR ds:0x629,dl
 620:   8a 16 29 06             mov    dl,BYTE PTR ds:0x629
 624:   ea 00 7c 00 00          jmp    0x0:0x7c00
    ...
 7bd:   00 80 01 00             add    BYTE PTR [bx+si+0x1],al
 7c1:   05 17 01                add    ax,0x117
 7c4:   03 01                   add    ax,WORD PTR [bx+di]
 7c6:   04 00                   add    al,0x0
 7c8:   00 00                   add    BYTE PTR [bx+si],al
 7ca:   04 00                   add    al,0x0
    ...
 7fc:   00 00                   add    BYTE PTR [bx+si],al
 7fe:   55                      push   bp
 7ff:   aa                      stos   BYTE PTR es:[di],al