mer*_*011 2 linux x86 assembly gnu-assembler
这里有几个相关的问题.考虑一个仅包含以下两条指令的程序
movq 1, %rax
cpuid
Run Code Online (Sandbox Code Playgroud)
如果我把它扔进一个名为的文件Foo.asm,并运行as Foo.asm,as那么便携式GNU汇编器,我将a.out在我的系统上得到一个大小为665字节的文件.
如果我然后chmod 700 a.out尝试./a.out,我会收到一个错误说cannot execute binary file.
asm指令翻译成二进制文件,为什么文件如此之大?asm输入文件中指令的二进制操作码,而不是一堆额外的东西?如果我只是试图将两个asm指令转换为二进制文件,为什么文件如此之大?
因为汇编程序创建了一个relocatable object file包含附加信息的内容,例如内存段和符号表.
为什么不能执行二进制文件?
因为它是一个(可重定位的)object file,而不是一个loadable file.您需要链接它以使其可执行,以便操作系统可以加载它:
$ ld -o Foo a.out
Run Code Online (Sandbox Code Playgroud)
您还需要通过指定_start符号为链接器提供程序启动位置的提示.
但是,仍然,Foo可执行文件比您预期的要大,因为它仍然包含elf header操作系统实际启动程序所需的其他信息(例如).
此外,如果您现在启动可执行文件,它将导致a segmentation fault,因为您正在加载address未映射到您的地址空间的1 的内容rax.尽管如此,如果你解决这个问题,程序最后会遇到未定义的代码 - 你需要确保通过a优雅地退出程序syscall.
最小的运行示例(假设为x86_64架构)看起来像
.globl _start
_start:
movq $1, %rax
cpuid
mov $60, %rax # System-call "sys_exit"
mov $0, %rdi # exit code 0
syscall
Run Code Online (Sandbox Code Playgroud)如何在输入文件中准确获取asm指令的二进制操作码,而不是一堆额外的东西?
您可以使用objcopy从目标文件生成原始二进制图像:
$ objcopy -O binary a.out Foo.bin
Run Code Online (Sandbox Code Playgroud)
然后,Foo.bin将只包含指令操作码.
nasm有一个-f bin选项,可以创建汇编代码的二进制表示.我使用它来为VirtualBox实现一个裸引导加载程序(警告:未记录,仅原型!),以便在没有操作系统的情况下直接在VirtualBox映像中启动二进制代码.
一旦得到3的答案,我怎样才能让我的处理器执行它们?
您将无法在Linux下直接执行原始二进制文件.您需要为此编写自己的加载器或根本不使用操作系统.例如,请参阅上面的裸引导加载程序链接 - 这将操作码写入VirtualBox光盘映像的引导加载程序,以便在启动VirtualBox机器时执行指令.