gpt4 book ai didi

assembly - 如何告诉 GNU 汇编器在使用未定义的标签时发出警告?

转载 作者:行者123 更新时间:2023-12-03 06:39:57 24 4
gpt4 key购买 nike

有没有办法告诉 GNU 汇编器在编译时使用未定义的标签发出警告?

假设我犯了一个拼写错误:

jmp MyLabell

MyLabel:

我不使用链接器。我使用 as 生成目标文件,然后使用 objcopy.o 文件转换为原始二进制文件。我这样做是因为我打算在只能执行原始二进制文件(实模式引导加载程序)的环境中运行它。我认为如果我在汇编源代码时使用了未定义的标签,汇编器会警告我

它会编译得很好,但由于 MyLabell 从未定义过,它总是会转换为地址 0,让程序员毫 headless 绪和健忘。 可以告诉as不要忽略此类问题吗?如果不能,是否有理由认为这是不可能的?据我所知(如果我错了,请纠正我),NASM 确实关心我仅使用定义的标签。

我使用的 GNU 汇编器版本:GNU 汇编器 (GNU Binutils) 2.29.1

我已经花了一整晚调试我的代码,只是为了发现重命名标签后,我没有更改对它的所有引用。

最佳答案

这本质上是一个XY problem

为了回答最初的问题,GNU 汇编器 as 假设它在当前文件中找不到的任何标签都位于另一个文件中,该文件将在链接时由链接器解析。它将一个虚拟值放置为由链接器解析的跳转目标。

<小时/>

问题归结为这样一个事实:您从未发现标签是否未定义,因为您没有通过链接器运行它来生成可执行文件。将原始对象文件转换为平面二进制文件可能无法按预期工作。要解决此问题:

  • 使用 GNU 汇编器生成目标文件。
  • 使用链接器LD设置原点
  • 使用 OBJCOPY 将最终链接的可执行文件转换为二进制文件。
<小时/>

如果您要创建实模式引导加载程序,请勿在 GNU 汇编器中使用 .org 指令。它不会做你期望的事情。这与 NASM 在直接生成原始二进制文件时使用的 org 指令不同。你可以使用类似的东西:

as --32 boot.s -o boot.o
ld -melf_i386 -nostdlib -Ttext=0x7c00 boot.o -o boot.elf
objcopy -O binary boot.elf boot.bin

使用示例中的LD命令,您可以指定任意数量的.o文件链接在一起,或者根据需要指定一个目标文件。

<小时/>

作为最后一节的附录,我更喜欢使用带 LD 的链接器脚本。对于引导加载程序,我使用链接器将引导签名放置在适当的位置(可以从汇编文件中删除它),并将原点设置为 0x7c00。这是一个非常简单的方法,假设您的引导加载程序仅使用 .text.data 甚至 .rodata 部分:

文件link.ld:

OUTPUT_FORMAT("elf32-i386");
ENTRY(start);
SECTIONS
{
. = 0x7C00;
.text : {
*(.text);
}
.data : {
*(.data);
*(.rodata);
}

/* Boot signature */
.sig : AT(0x7DFE) {
SHORT(0xaa55);
}

/* Discard common unwanted/unneeded sections */
/DISCARD/ : {
*(.comment);
*(.note.gnu.build-id);
}
}

然后汇编并链接该文件。在本例中,我们指定 -Tlink.ld 使用上面的链接描述文件,并且不再需要使用 -Ttext=0x7c00:

as --32 boot.s -o boot.o
ld -melf_i386 -nostdlib -Tlink.ld boot.o -o boot.elf
objcopy -O binary boot.elf boot.bin
<小时/>

如果找不到像 MyLabel1 这样的标签,正确使用链接器生成可执行文件应该会产生类似的错误:

boot.o:(.text+0x1): undefined reference to `MyLabell'

<小时/>

原点和实模式代码

GNU 链接器无法理解 real mode 20-bit segment:offset addressing 。引导加载程序将在物理地址 0x07c00 处加载,但有不止一种方法可以寻址该位置。在实模式中段:偏移寻址段和偏移量结合起来定义物理地址。计算方式为段* 16 + 偏移量。您在链接描述文件或 .Ttext= 选项中选择的起始点必须与加载到段寄存器(尤其是 DS)中的段结合起来,为 0x07c00。如果将段设置为 0x0000,则所需的偏移量为 0x7c00,因为 0x0000 * 16 + 0x7c00 = 0x07c00。使用 0x7c0 段,您需要 0x0000 的偏移量,即 0x7c0 * 16 + 0x0000 = 0x07c00。

我的链接器脚本link.ld假设您使用0x0000加载了DS段寄存器。您用于段的值是 0x7c0,因此您需要更改 link.ld 以使用 。 = 0x0000; 而不是 。 = 0x7C00;.

如果您使用。 = 0x0000 作为原点,那么您还需要通过从中减去 0x7c00 来调整引导加载程序位置。 .sig : AT(0x7DFE) { 行必须更改为 .sig : AT(0x1FE) {。如果您不使用链接器脚本并指定运行 LD 时的原点,则必须将其更改为 -Ttext=0x0000

关于assembly - 如何告诉 GNU 汇编器在使用未定义的标签时发出警告?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47480109/

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