将英特尔代码与反汇编输出相匹配

Matching the intel codes to disassembly output

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

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

.globl _start
_start:
    movq ,    %rax    # move immediate into 8-byte rax (rax)
    movl ,    %eax    # move immediate into 4-byte rax (eax)
    movw ,    %ax     # move immediate into 2-byte rax (ax)
    movb ,    %al     # move immediate into 1-byte rax (al)
    mov ,    %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    [=11=]x1,%rax
  40007f:   b8 01 00 00 00          mov    [=11=]x1,%eax
  400084:   66 b8 01 00             mov    [=11=]x1,%ax
  400088:   b0 01                   mov    [=11=]x1,%al

  40008a:   b8 3c 00 00 00          mov    [=11=]x3c,%eax
  40008f:   0f 05                   syscall

现在,匹配来自 MOV 的英特尔代码,复制到这里:

我能够协调以下四个指令:

  1. mov [=15=]x1,%al --> b0 01
    YES,intel 状态代码是 b0 [+ 1 byte for value] for 1-byte move immediate.
  2. mov [=18=]x1,%eax --> b8 01 00 00 00
    YES,intel 状态代码是 b8 [+ 4 bytes for value] for 1-byte move immediate.
  3. mov [=21=]x1,%ax --> 66 b8 01 00
    ,英特尔状态代码是b8而不是66 b8
  4. mov [=25=]x1,%rax48 --> c7 c0 01 00 00 00
    N/A,仅限 32 位指令。未列出。

据此,我的相关问题是:

您遗漏了前缀“操作码”的(概念),它改变了后续指令的含义。 IA32 manual 第 2 卷第 2.1.1 节和第 2.2.1 节对此进行了介绍。从 2.1.1 我们得到:

Operand-size override prefix is encoded using 66H (66H is also used as a mandatory prefix for some instructions).

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

最后一个案例(mov , %rax)实际上使用了不同的指令

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

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