是否可以使用`as`组装和运行原始CPU指令?

时间:2014-03-13 10:52:06

标签: linux assembly x86 gas

这里有几个相关的问题。 考虑一个仅包含以下两条指令的程序

movq 1, %rax
cpuid

如果我把它扔进一个名为Foo.asm的文件中,并运行as Foo.asm,其中as是可移植的GNU汇编程序,我将得到一个名为a.out的文件,在我的系统上大小为665字节。

如果我然后chmod 700 a.out并尝试./a.out,我会收到错误cannot execute binary file

  1. 如果我只想将两条asm指令翻译成二进制文件,为什么文件太大?
  2. 为什么不能执行二进制文件?我提供有效的指令,所以我希望CPU能够执行它们。
  3. 如何准确获取输入文件中asm指令的二进制操作码,而不是一堆额外的东西?
  4. 一旦得到3的答案,我怎样才能让我的处理器执行它们? (假设我没有运行特权指令。)

3 个答案:

答案 0 :(得分:9)

  1. 如果我只想将两个asm指令翻译成二进制文件,为什么文件太大?

    因为汇编程序创建了一个relocatable object file,其中包含其他信息,例如内存部分符号表

  2. 为什么不能执行二进制文件?

    因为它是(可重定位的)object file,而不是loadable file。您需要链接它以使其可执行,以便操作系统可以加载它:

    $ ld  -o Foo a.out
    

    您还需要通过指定_start符号,向链接器提供有关程序启动位置的提示。

    但是,然而,Foo可执行文件仍然比您预期的要大,因为它仍然包含操作系统实际启动程序所需的其他信息(例如elf header)。

    此外,如果您现在启动可执行文件,则会生成segmentation fault,因为您要将address 1的内容(未映射到您的地址空间)加载到{{1} }}。尽管如此,如果你解决这个问题,程序最后会遇到未定义的代码 - 你需要确保通过rax优雅地退出程序。

    最小运行示例(假设x86_64架构)看起来像

    syscall
  3. 如何在输入文件中准确获取asm指令的二进制操作码,而不是一堆额外的东西?

    • You can use objcopy目标文件生成二进制图像

      .globl  _start
      _start:
          movq $1, %rax
          cpuid
      
          mov     $60, %rax       # System-call "sys_exit"
          mov     $0, %rdi        # exit code 0
          syscall
      

      然后,$ objcopy -O binary a.out Foo.bin 包含指令操作码。

    • nasm有一个Foo.bin选项,可以创建汇编代码的二进制表示形式。我使用它来实现bare boot loader for VirtualBox(警告:未记录,仅原型!),以在没有操作系统的情况下直接在VirtualBox图像中启动二进制代码。

  4. 一旦我得到3的答案,我怎样才能让我的处理器执行它们?

    您将无法在Linux下直接执行原始二进制文件。您需要为此编写自己的加载器或根本不使用操作系统。例如,请参阅上面的裸引导加载程序链接 - 这将操作码写入VirtualBox光盘映像的引导加载程序,以便在启动VirtualBox机器时执行这些指令。

答案 1 :(得分:1)

对于GNU工具集,也许有类似于exe2bin实用程序的东西。我已经使用各种版本的exe2bin和Microsoft工具,ARM工具包可以生成二进制文件,但我不记得它是直接来自链接输出还是类似exe2bin。

答案 2 :(得分:1)

旧的MS-DOS COM文件格式不包含标头。它实际上只包含二进制可执行代码。但是,代码大小不能超过64kb。我不知道Linux是否可以执行这些。

相关问题