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
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
我个人不会使用这种方法,因为使用我在之前关于
你的基本问题是你实际上并没有将两个数字相加,而是将两个符号相加,而汇编程序通常不允许这样做。这是因为目标文件格式没有任何方法可以将添加两个符号表示为重定位,那是因为添加两个符号并没有多大意义。虽然在这种情况下您正在生成一个不支持重定位的二进制文件,因此汇编器可以发明自己的虚拟重定位来处理这个问题,但显然这在 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