匹配英特尔代码以反汇编输出

问题描述

我开始使用英特尔参考页来查找和了解操作码(而不是询问SO的所有内容)。我想确保我的理解没问题,并询问基本的asm程序和intel指令代码间的输出问题。

这是我必须将各种mov指令比较到rax-ish寄存器中的程序(是否有更好的方式来说“ rax”及其32-16位和8位组件?):

.globl _start
_start:
    movq $1,%rax    # move immediate into 8-byte rax (rax)
    movl $1,%eax    # move immediate into 4-byte rax (eax)
    movw $1,%ax     # move immediate into 2-byte rax (ax)
    movb $1,%al     # move immediate into 1-byte rax (al)
    mov $60,%eax
    syscall

其拆卸如下:

$ objdump -D file

file:     file format elf64-x86-64


disassembly of section .text:

0000000000400078 <_start>:

  400078:   48 c7 c0 01 00 00 00    mov    $0x1,%rax
  40007f:   b8 01 00 00 00          mov    $0x1,%eax
  400084:   66 b8 01 00             mov    $0x1,%ax
  400088:   b0 01                   mov    $0x1,%al

  40008a:   b8 3c 00 00 00          mov    $0x3c,%eax
  40008f:   0f 05                   syscall

现在,与MOV中的英特尔代码匹配,并复制到此处:

-

我能够调和以下四个说明:

  1. mov $0x1,%al-> b0 01
    ,英特尔州代码b0 [+ 1个字节的值],用于立即移动1个字节。
  2. mov $0x1,%eax-> b8 01 00 00 00
    ,英特尔州代码b8 [+ 4个字节的值],用于立即移动1个字节。
  3. mov $0x1,%ax-> 66 b8 01 00
    ,英特尔州代码b8而非66 b8
  4. mov $0x1,%rax48-> c7 c0 01 00 00 00
    不适用,仅32位指令。未列出。

与此相关的我的问题是:

  • mov $0x1,%ax为什么不匹配?
  • 64代码是否有相同的表,或者建议使用哪种查找方式?
  • 最后,当寄存器更改时,代码如何调整?例如,如果我想将值移到%ebx%r11上。您如何计算“代码调整量”,就像在此查找表中一样,它只提供(我认为?)“ eax”寄存器作为“注册示例代码”。

解决方法

您缺少更改以下指令含义的前缀“操作码”(的概念)。 IA32 manual的第2卷第2.1.1和2.2.1节对此进行了介绍。从2.1.1得到:

Operand-size覆盖前缀使用66H编码(66H还用作某些应用程序的强制前缀 说明)。

因此66前缀会将操作数大小从默认的32位更改为16位。因此,mov $1,%ax(16位)与mov $1,%eax(32位)相同,只是前缀为66

最后一种情况(mov $1,%rax)实际上使用了另一条指令

REX.W + C7 /0 io    MOV r/m64,imm32      Move imm32 sign extended to 64-bits tor/m64.

在这里,我们将常量移到任何寄存器中,而不是A-指令大了一个字节,但允许将32位的imim移到64位寄存器中,因此只需要4字节的常量而不是一个8字节(因此比等效的48 b8 01 00 00 00 00 00 00 00要小3个字节)。