assembly - 带有段寄存器的 x86-64 MOV 指令上的 REX.W 前缀
问题描述
我正在阅读x86/x64 开发人员手册,试图理解指令编码,但被段寄存器中的 mov 弄糊涂了,即本页的第 12 和第 13 形式。具体有两个问题:
(1) 两者都标有 REX.W 前缀,但据我了解,此标志仅在操作数大小为 64 位时使用。我知道为什么它应该与 r64 一起使用,但除此之外,为什么这两条指令都标有 REX.W 前缀?
(2) 两条指令中都有一个m16目的地,不是重复吗?为什么这两个指令首先是分开的?
对于 (2),我能想到的一个原因是,在第一种形式中,可以使用 66H 前缀选择 r16/r32,而当 REX.W 存在时(对于 r64)会忽略 66H。但是 66H 似乎也不适用于 m16,为什么它包含在第二种形式(r64/m16)中?
解决方案
我认为这是一个编辑错误。我认为应该从第 12 行省略 REX 前缀,以与第 11 行的 16 位形式和第 13 行的 64 位形式(就像有 16-32 和 64 位形式对于其他变体)。
(也许有人试图将这三种形式组合成一行。该条目的“描述”列显示“将零扩展 16 位段寄存器移动到 r16/r32/ r64 /m16 ”,所以这与有人开始合并行,然后意识到该r64
行应该是单独的,但忘记从 16/32 位行中删除 REX.W。)
我认为 m16 出现在所有三种形式上的原因是从段寄存器到内存的移动始终是 16 bits,无论操作数大小如何。 mov
来自 SR 是一个奇怪的指令。
没有理由使用 64 位形式:所有支持 64 位模式的 CPU 都零扩展至没有前缀的完整寄存器大小。
对于 ... 和所有 Intel 64 处理器,目标寄存器的高位为零。
例外情况是比 Pentium Pro 更早的仅 32 位 CPU,以及同样仅 32 位的Quark(基于 P5)。
我没有查看 AMD 手册以查看是否有任何 AMD64 CPU 可能会留下未定义或未修改的 RAX 的高 6 字节8c d8
(mov eax,ds
没有前缀)。但是 Intel 的手册很清楚,所有 Intel64 CPU 都将零扩展为 32 位(因此在写入 32 位寄存器时总是隐含到 64 位)。
操作数大小前缀可66h
用于编码66 8c d8
( mov ax,ds
),它使 RAX 的高字节保持不变(就像总是写入 16 位寄存器一样)。
通常你永远不会想要这个,但操作数大小前缀确实会影响mov reg, SR
与 REX.W 不同。
推荐阅读
- php - php-mysql重复行
- mysql - 合并具有缺失值的集合 laravel
- java - 为什么 String.split(":") 不能正常工作?
- angular - 垫子对话框中垫子选择的打开选项列表未关闭
- sql - sql查询速度慢如何优化
- react-native - 如何在本机反应中检查设备是否连接到蓝牙?
- python - 如何通过表格和图表图像制作下面描述的 CNN 网络?
- selenium-webdriver - 向远程 WebDriver 服务器 URL 发送 HTTP 请求时抛出空响应,异常是 ServerProtocolviolation
- c# - DotNet Core 在启动后设置连接字符串已经运行
- swift - Swift 中的 M13Checkbox 选定操作?