将英特尔代码与反汇编输出相匹配
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
的英特尔代码,复制到这里:
我能够协调以下四个指令:
mov [=15=]x1,%al
--> b0 01
YES,intel 状态代码是 b0
[+ 1 byte for value] for 1-byte move immediate.
mov [=18=]x1,%eax
--> b8 01 00 00 00
YES,intel 状态代码是 b8
[+ 4 bytes for value] for 1-byte move immediate.
mov [=21=]x1,%ax
--> 66 b8 01 00
否,英特尔状态代码是b8
而不是66 b8
。
mov [=25=]x1,%rax48
--> c7 c0 01 00 00 00
N/A,仅限 32 位指令。未列出。
据此,我的相关问题是:
- 为什么
mov [=27=]x1,%ax
不匹配?
64
位代码是否有相同的 table,或者建议的查找方式是什么?
- 最后,寄存器变化时代码如何调整?例如,如果我想将值移动到
%ebx
或 %r11
。你如何计算 'code-adjustment',因为它看起来像在这个查找 table 中它只给出(我认为?) eax
寄存器 'register example codes'.
您遗漏了前缀“操作码”的(概念),它改变了后续指令的含义。 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 个字节)
我开始使用 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
的英特尔代码,复制到这里:
我能够协调以下四个指令:
mov [=15=]x1,%al
-->b0 01
YES,intel 状态代码是b0
[+ 1 byte for value] for 1-byte move immediate.mov [=18=]x1,%eax
-->b8 01 00 00 00
YES,intel 状态代码是b8
[+ 4 bytes for value] for 1-byte move immediate.mov [=21=]x1,%ax
-->66 b8 01 00
否,英特尔状态代码是b8
而不是66 b8
。mov [=25=]x1,%rax48
-->c7 c0 01 00 00 00
N/A,仅限 32 位指令。未列出。
据此,我的相关问题是:
- 为什么
mov [=27=]x1,%ax
不匹配? 64
位代码是否有相同的 table,或者建议的查找方式是什么?- 最后,寄存器变化时代码如何调整?例如,如果我想将值移动到
%ebx
或%r11
。你如何计算 'code-adjustment',因为它看起来像在这个查找 table 中它只给出(我认为?)eax
寄存器 'register example codes'.
您遗漏了前缀“操作码”的(概念),它改变了后续指令的含义。 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 个字节)