gpt4 book ai didi

assembly - YASM [symbol + $$]有效地址在平面二进制格式中太复杂

转载 作者:行者123 更新时间:2023-12-02 08:04:01 26 4
gpt4 key购买 nike

org 0x7c00是在平面二进制文件中获取正确绝对地址的正常方法,但我对我希望使用的另一种方法感到好奇。

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

mov [symbol+$$], register


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

据我了解, symbol+$$应该能够处理成一个数字(而不是一个段+偏移量),对吗?如果我错了,请告诉我,但是如果我错了,为什么YASM告诉我地址​​太复杂了?

还有其他方法可以使用 start=和/或 vstart=代替 org并仍然获得正确的绝对寻址吗?

使用 [symbol]无效。汇编为 [0000]的绝对地址



之所以要这样做,是因为我有一个用于重定位自身的引导加载程序的二进制机器代码,但是在重定位之前它会在一些符号中存储一些值(例如,在

YASM支持带有“节”的二进制程序,该节可以具有不同的寻址偏移量,所以我要做的是代码设置,其中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并没有将其实现为一般规则的例外。

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

在通常情况下(可能会生成目标文件时),添加两个符号没有意义,原因是符号不仅仅是数字。它们还引用一个部分,并且这些部分最终可能驻留在内存中的任何位置。您的[bootdrive + $$]表达式表示要获取加载到内存中的bootdrive的实际地址,并将其添加到当前节开始的实际地址中。当生成目标文件时,汇编器将不知道这些实际地址是什么,符号所属的节可以放在任何地方。即使链接器可能也不知道,如果它正在生成可重定位的可执行文件,则将取决于操作系统在何处加载可执行文件。

(这忽略了以下事实:您已经告诉汇编程序,应将bootdrive的实际地址与汇编程序认为的实际地址不同。这也是汇编程序在通常的输出情况下不支持的东西。对象文件。)

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

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

您很难说服它们的原因是,即使使用二进制文件,即使可以,添加两个符号也没有任何意义。您的示例代码仅会起作用,因为bootdrive的地址不是其实际地址。确实,向其中添加$$的原因是为了计算其实际地址。由于您的示例用例是人为设计的,因此是不必要的,因此有更好的方法来编写可自行重定位的引导加载程序,因此对于添加两个符号为何有意义,它并没有很好的论据。

可能没有直接的解决方法

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

虽然我确定还有其他解决问题的方法,但仍然可以使您使用要使用的section指令完成所需的工作,但我不会费心尝试找出可能是什么。相反,我将建议您一种您不想要的解决方法,如果不是为了您自己的利益,那么是为了其他可能会遇到类似情况的人的利益。

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

我的解决方案是不使用段指令来解决引导扇区位于两个不同地址的问题。相反,您可以使用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。实际上,由于通常不需要修改MBR引导扇区中的DL,因此可以完全省去DL。 TIMES指令用于确保分区表和幻数位于所需的位置。

这是 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

关于assembly - YASM [symbol + $$]有效地址在平面二进制格式中太复杂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59010047/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com