【发布时间】:2020-09-13 20:04:58
【问题描述】:
我开始使用英特尔参考页面来查找和了解操作码(而不是在 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 的英特尔代码,复制到这里:
我能够协调以下四个指令:
-
mov $0x1,%al-->b0 01
是,英特尔声明代码是b0[+ 1 byte for value] 用于 1 字节立即移动。 -
mov $0x1,%eax-->b8 01 00 00 00
是,英特尔声明代码为b8[+ 4 bytes for value] 用于 1 字节立即移动。 -
mov $0x1,%ax-->66 b8 01 00
否,英特尔声明代码是b8而不是66 b8。 -
mov $0x1,%rax48-->c7 c0 01 00 00 00
N/A,仅限 32 位指令。未列出。
由此,我与此相关的问题是:
- 为什么
mov $0x1,%ax不匹配? -
64-bit 代码是否有相同的表,或者建议的查找方法是什么? - 最后,当寄存器发生变化时,代码如何调整?例如,如果我想将一个值移动到
%ebx或%r11。您如何计算“代码调整”,就像在此查找表中所示,它仅提供(我认为?)eax用于“注册示例代码”的注册。
【问题讨论】:
-
这些条目让您决定使用操作数大小前缀 (
66) 还是不获取 32 位和 64 位模式下的 16 位操作数大小,或者 32 位操作数 - 16 位模式下的大小。66是前缀而不是操作码。48是 W=1 的 REX 前缀。再次,查找前缀后面的操作码。 -
另外,对于 64 位,不要再看旧版本的英特尔手册了。 felixcloutier.com/x86/mov 是从当前版本的英特尔 PDF 中提取的。或者,由于您需要了解手册条目的额外信息,只需阅读英特尔的实际 PDF,包括第 2 卷中的介绍章节。 stackoverflow.com/tags/x86/info中的链接和更多内容@
-
@PeterCordes 哦,那好多了,谢谢你的链接(它还支持在 html 中搜索,其他版本不支持)。
-
也相关:How many ways to set a register to zero? 提到了 32 位或 64 位寄存器的
mov的 3 种不同形式。
标签: assembly x86 x86-64 intel machine-code