【问题标题】:OpCode compression, decompression and encoding differences?OpCode压缩、解压和编码的区别?
【发布时间】:2023-03-09 22:02:02
【问题描述】:

我有一个简单的.asm 文件:

    BITS 64

        SECTION .text
        global main

    main:
        mov rax, 0x2a     ; 42

mov 语句实际上是使用以下命令行编译成机器代码的全部内容:

nasm.exe -o load_rax.bin -f bin load_rax.asm

...得到的二进制输出是:

0xb8 0x2a 0x00 0x00 0x00

当我通过this Online x86 / x64 Assembler and Disassembler 编译相同的mov 指令时,我得到了完全不同的东西:

0x48 0xc7 0xc0 0x2a 0x00 0x00 0x00

我在通过 NASM 编译时做错了吗?我知道可能正在进行操作码压缩,如果是这种情况,那么我希望能够处理它,但是我需要知道指令是否已被压缩,如何判断以及使用了什么算法.

我只在 64 位中工作。

任何关于为什么这些二进制文件不同的想法都会非常有帮助。

【问题讨论】:

  • 有时有多种不同的方式来编码相同的指令,在这种情况下,汇编器(应该)选择最小的编码,如果有多个最短的编码,那么选择是任意的。在某些情况下,有较短的指令与给定的(但不同的)指令执行完全相同的操作,并且汇编程序通常会替换较短的指令作为优化。没有进行“操作码压缩”。

标签: assembly 64-bit nasm x86-64


【解决方案1】:

b8 2a 00 00 00mov r32, imm32 的一个实例,
48 c7 c0 2a 00 00 00mov r/m64, imm32 的一个实例

我想,有一个论点认为更长的编码是“你要求的”,因为它像你告诉它的那样明确地写入 64 位版本的寄存器。另一方面,以这种方式对其进行编码是没有用的,因为对 32 位寄存器的写入无论如何都是零扩展的,所以 NASM 编码并没有错,它只是让你的代码在字面上稍微少了一点。

【讨论】:

  • 这对我来说没有意义:mov eax, 0x2a 编译为 0x66 0xb8 0x2a 0x00 0x00 0x00。 Intel IA-32手册是否给出了操作码->机器码转换?
  • @IAbstract 您正在 16 位模式下进行汇编(BITS 16 隐含在 -f bin 中)因此它需要一个操作数大小前缀 0x66 以使其成为 32 位指令而不是一个 16 位的 (mov ax, 0x2a)。在 32 位和 64 位模式下则相反,需要一个操作数大小前缀才能使其成为 16 位操作。
  • 是的 - 0000000000000000
    : 0: b8 2a 00 00 00 mov eax,0x2a nasm -f elf64 -g -F dwarf stuff.s -o stuff.o
  • @IAbstract 该手册在第 3 章的第一列中都有编码,在第 2 章中您可能需要一些额外的规则,附录 B 也很有用。不过要小心错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-30
  • 2012-04-26
  • 2016-12-26
  • 1970-01-01
  • 2016-08-05
  • 2019-01-29
  • 2012-12-02
相关资源
最近更新 更多