x64 汇编中 MOV、MOVZX 和 MOVSX 的区别
2025-04-11
2
0
1. MOV 指令
功能
- 通用的数据传送指令。
- 操作数大小必须相同(例如
mov eax, ebx
合法,但mov eax, bl
非法)。
高位处理
- 如果操作寄存器的一部分(如
AL
→AX
),直接复制低位数据,不修改高位。 - 高位可能残留旧值,导致不可预测的结果。
示例
mov al, 0xFF ; AL = 0xFF(8位)
mov ax, al ; AX = 0x??FF(假设 AX 原值为 0x1234,则结果为 0x12FF)
2. MOVZX 指令(零扩展)
功能
- 将较小的无符号数传送到较大的目标,并用零填充高位。
- 适用于无符号数扩展(例如
0xFF
视为 255)。
规则
- 源操作数 < 目标操作数(如
BYTE
→DWORD
)。
示例
mov bl, 0xFF ; BL = 0xFF(8位)
movzx eax, bl ; EAX = 0x000000FF(32位,高位清零)
3. MOVSX 指令(符号扩展)
功能
- 将较小的有符号数传送到较大的目标,并用符号位填充高位。
- 适用于有符号数扩展(例如
0xFF
视为 -1)。
规则
- 源操作数 < 目标操作数(如
BYTE
→DWORD
)。
示例
mov bl, 0xFF ; BL = 0xFF(8位,有符号数 -1)
movsx eax, bl ; EAX = 0xFFFFFFFF(32位,符号位填充)
对比总结
特性 | MOV |
MOVZX |
MOVSX |
---|---|---|---|
操作数大小 | 必须相同 | 源 < 目标 | 源 < 目标 |
高位处理 | 不修改高位(可能残留旧值) | 强制清零高位 | 用符号位填充高位 |
用途 | 通用数据传输 | 无符号数扩展 | 有符号数扩展 |
安全性 | 不安全(高位未定义) | 安全(明确清零) | 安全(明确符号扩展) |
关键示例对比
场景:将 BYTE
类型的 0xFF
扩展到 DWORD
mov bl, 0xFF ; BL = 0xFF
; 使用 MOV(非法)
; mov eax, bl ; 编译错误!
; 使用 MOVZX(无符号扩展)
movzx eax, bl ; EAX = 0x000000FF(十进制 255)
; 使用 MOVSX(有符号扩展)
movsx eax, bl ; EAX = 0xFFFFFFFF(十进制 -1)
何时使用?
MOV
- 源和目标操作数大小完全相同(例如
mov eax, ebx
)。
- 源和目标操作数大小完全相同(例如
MOVZX
- 扩展无符号数(例如图像像素值
0x80
→0x00000080
)。
- 扩展无符号数(例如图像像素值
MOVSX
- 扩展有符号数(例如
-1
→0xFFFFFFFF
)。
- 扩展有符号数(例如
总结
MOV
:基础数据传输,操作数大小需一致。MOVZX
:无符号数扩展,高位填零。MOVSX
:有符号数扩展,高位填符号位。
理解这些指令的区别,可避免数据截断或符号错误导致的隐蔽问题。
movsx和movsxd指令区别详解
根据一些资料,movsxd实际上是movsx的一种特定形式,专门处理32位到64位的扩展。在早期的x86架构中,movsx可以处理字节到字、字到双字,但在64位模式下,当需要将双字扩展到四字时,引入了movsxd指令。可能的原因是原有的movsx在操作数大小上可能不够明确,或者编码不同。
movsxd
(Move with Sign-Extension Doubleword to Quadword)和 movsx
(Move with Sign-Extension)是 x86/x86-64 指令集中用于符号扩展的指令,但它们的应用场景和操作数大小有所不同:
1. movsx 指令
- 功能:将较小尺寸的源操作数(8/16/32 位)符号扩展到较大尺寸的目标操作数(16/32/64 位)。
- 支持的扩展类型:
- 8 位 → 16/32/64 位(例如:
movsx eax, byte [mem]
) - 16 位 → 32/64 位(例如:
movsx rax, word [mem]
) - 32 位 → 64 位(仅在 x86-64 模式下,需用
movsxd
,见下文)。
- 8 位 → 16/32/64 位(例如:
- 适用模式:
- 32 位模式(扩展至 16/32 位)。
- 64 位模式(扩展至 16/32/64 位,但 32→64 需用
movsxd
)。
2. movsxd 指令
- 功能:专用于在 x86-64 模式下将 32 位操作数符号扩展到 64 位。
- 支持的扩展类型:
- 32 位 → 64 位(例如:
movsxd rax, dword [mem]
)。
- 32 位 → 64 位(例如:
- 适用模式:
- 仅限 64 位模式(x86-64)。
关键区别
特性 | movsx |
movsxd |
---|---|---|
操作数大小 | 8→16/32/64,16→32/64,32→64(需显式) | 仅 32→64 |
编码/助记符 | 通用符号扩展(多种组合) | 专用于 32→64 扩展 |
64 位模式必需性 | 支持多种扩展,但 32→64 必须用 movsxd |
唯一合法用于 32→64 的指令 |
示例
; 在 64 位模式下:
movsx rax, bl ; 8位 → 64位(符号扩展)
movsx eax, bx ; 16位 → 32位(符号扩展)
movsxd rax, ebx ; 32位 → 64位(符号扩展)
; 错误用法:
; movsx rax, ebx ; 不合法!必须用 movsxd
总结
movsx
:通用符号扩展指令,支持多种源和目标大小组合。movsxd
:x86-64 专用指令,仅处理 32→64 位的符号扩展。- 在 64 位代码中,将 32 位值扩展到 64 位时,必须使用
movsxd
。