天然气中是否存在像鼻子这样的组织?

时间:2015-07-17 15:12:41

标签: assembly nasm gas

在nasm中,当我输入

bits 32
org 1
jmp mylabel
mylabel:

组织指令将所有标签的地址偏移1。 但是,当我在GAS中这样做时:

.org 1
jmp mylabel
mylabel:

我得到一个文件,其中标签地址与程序没有组织相同,但编译文件中有1个前导0。 GAS中是否有类似于来自nasm的组织的指令?

1 个答案:

答案 0 :(得分:3)

GNU汇编程序没有与NASM的ORG指令等效的指令。 GNU汇编程序的.ORG指令更像是MASM的ORG指令,它可能是NASM和GAS指令的模型。

NASM的ORG指令比GAS或MASMs指令更受限制。正如Frank Kotler所说,它只适用于“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文件是简单的二进制文件。文件中没有与其他可执行格式一样存储的标题或其他信息,只有原始二进制图像。该文件从偏移量0x100开始加载到单个16位段中。所以这就像你的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

请注意,上述命令不适用于GNU汇编程序和链接程序的Windows PECOFF版本。您需要在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=选项。