GNU 汇编器没有与 NASM 的 ORG 指令等效的指令。 GNU 汇编器的 .ORG 指令更像 MASM 的 ORG 指令,这可能是 NASM 和 GAS 指令的模型。
NASM 的 ORG 指令比 GAS 或 MASMs 指令更受限制。正如弗兰克科特勒所说,它只适用于“bin”输出格式,并且只能在源文件中使用一次。来自NASM Manual:
与 MASM 兼容的汇编器提供的 ORG 指令不同,后者
允许您在目标文件中跳转并覆盖您拥有的代码
NASM 的 ORG 已经生成,完全按照指令所说的:起源。
它的唯一功能是指定一个偏移量,该偏移量被添加到所有内部
地址在该部分内的引用;它不允许任何诡计
MASM 的版本可以。
GNU 汇编器 .ORG 指令不允许 MASM 的 ORG 指令所做的“诡计”。您不能向后移动原点并覆盖已生成的代码。然而,GAS 确实允许您多次使用它,最重要的是它适用于 ELF 和 PECOFF 等目标文件格式。没有办法使用这些目标文件格式来实现 NASM 的 ORG 指令的行为,因为没有办法说一个部分应该加载到特定地址。
正如 dwelch 所说,ORG 指令,无论您使用什么汇编程序,都只适用于单文件汇编项目。 NASM 强制这样做,因为它仅适用于无法链接的“bin”输出格式。对于 GAS 和 MASM,.ORG/ORG 指令仅与目标文件中部分/段的开头相关。这意味着如果您希望这些指令在链接图像中设置绝对地址,则带有指令的部分必须是第一个或唯一的部分,并且该部分必须从地址 0 开始。
要使用 GNU 汇编器和链接器获得您想要的行为,您需要两件事。首先,您希望生成的二进制图像在加载到 ORG 指令给出的绝对地址时工作。这意味着任何绝对内存引用都需要使用内存中被引用位置被加载到内存中的位置,而不是被引用位置在二进制文件中的位置。由于您的第二个要求,这两个位置不同。您的第二个要求是二进制文件从代码中的第一个位置开始,而不是地址 0。
为了向您展示如何使用 GNU 汇编器和链接器来做到这一点,我将使用一个更实际的示例来创建 MS-DOS .COM 文件。 COM 文件是简单的二进制文件。与其他可执行格式一样,文件中没有存储标头或其他信息,只有原始二进制图像。该文件被加载到单个 16 位段中,从偏移量 0x100 开始。所以这就像你的 NASM 示例一样,文件中的第一个字节不应该加载到地址 0。在这种情况下,它加载到地址 0x100。
所以这是一个简单的 MS-DOS “Hello, World!”程序,用 GNU 程序集编写:
.code16
.text
mov $msg,%dx
mov $9,%ah
int $0x21
mov $0x4c00,%ax
int $0x21
msg:
.ascii "Hello, world!$"
请注意,上面的源代码示例中没有 .ORG 指令。事实证明,它对创建未在地址 0 加载的二进制文件没有帮助。它可以正常组装,但要正确链接它,您需要使用 dwelch 提到的-Ttext= 选项:
as -o hello.o hello.s
ld -Ttext=0x100 --oformat binary -o hello.com hello.o
请注意,上述命令不适用于 Windows PECOFF 版本的 GNU 汇编器和链接器。您需要在 Linux 或其他使用 ELF 对象文件格式的机器上运行这些命令。
您可以看到链接器使用以下命令正确生成了 COM:
$ hd hello.com
00000000 ba 0c 01 b4 09 cd 21 b8 00 4c cd 21 48 65 6c 6c |......!..L.!Hell|
00000010 6f 2c 20 77 6f 72 6c 64 21 24 |o, world!$|
0000001a
$ objdump -b binary -m i8086 --adjust-vma=0x100 -D hello.com
...
00000100 <.data>:
100: ba 0c 01 mov $0x10c,%dx
103: b4 09 mov $0x9,%ah
105: cd 21 int $0x21
107: b8 00 4c mov $0x4c00,%ax
10a: cd 21 int $0x21
10c: 48 dec %ax
10d: 65 gs
...
文件中的第一个字节是mov $msg,%dx指令,如hd所示。没有额外的字节填充 COM 文件的开头。 objdump 反汇编程序输出显示对符号 msg 的绝对内存引用已正确解析。它指向字符串将被加载到内存中的地址 (0x010c),而不是字符串在文件中的位置 (0x000c)。
对于将多个文件链接在一起或使用多个部分的更复杂的示例,您可能需要使用链接器脚本而不是 -Ttext= 选项。