首页 > 汇编语言 > 数据操作相关运算符和指令
阅读:10,292
汇编语言MOVZX和MOVSX指令
尽管 MOV 指令不能直接将较小的操作数复制到较大的操作数中,但是程序员可以想办法解决这个问题。假设要将 count(无符号,16 位)传送到 ECX(32 位),可以先将 ECX 设置为 0,然后将 count 传送到 CX:
下面例子的操作数是各种大小的寄存器:
如果一个十六进制常数的最大有效数字大于 7,那么它的最高位等于 1。如下例所示,传送到 BX 的十六进制数值为 A69B,因此,数字“A”就意味着最高位是 1。(A69B 前面的 0 是一种方便的表示法,用于防止汇编器将常数误认为标识符。)
.data count WORD 1 .code mov ecx,0 mov cx,count如果对一个有符号整数 -16 进行同样的操作会发生什么呢?
.data signedVal SWORD -16 ; FFF0h (-16) .code mov ecx,0 mov cx,signedVal ; ECX = 0000FFF0h(+ 65,52 0)ECX 中的值(+65 520)与 -16 完全不同。但是,如果先将 ECX 设置为 FFFFFFFFh,然后再把 signedVal 复制到 CX,那么最后的值就是完全正确的:
mov ecx,0FFFFFFFFh mov cx,signedVal ;ECX = FFFFFFF0h(-16)本例的有效结果是用源操作数的最高位(1)来填充目的操作数 ECX 的高 16 位,这种技术称为符号扩展(sign extension)。当然,不能总是假设源操作数的最高位是 1。幸运的是,Intel 的工程师在设计指令集时已经预见到了这个问题,因此,设置了 MOVZX 和 MOVSX 指令来分别处理无符号整数和有符号整数。
MOVZX 指令
MOVZX 指令(进行全零扩展并传送)将源操作数复制到目的操作数,并把目的操作数 0 扩展到 16 位或 32 位。这条指令只用于无符号整数,有三种不同的形式:
MOVZX reg32,reg/mem8
MOVZX reg32,reg/mem16
MOVZX reg16,reg/mem8
.data byteVal BYTE 10001111b .code movzx ax,byteVal ;AX = 0000000010001111b下图展示了如何将源操作数进行全零扩展,并送入 16 位目的操作数。
下面例子的操作数是各种大小的寄存器:
mov bx, 0A69Bh movzx eax, bx ;EAX = 0000A69Bh movzx edx, bl ;EDX = 0000009Bh movzx cx, bl ;CX = 009Bh下面例子的源操作数是内存操作数,执行结果是一样的:
.data byte1 BYTE 9Bh word1 WORD 0A69Bh .code movzx eax, word1 ;EAX = 0000A69Bh movzx edx, byte1 ;EDX = 0000009Bh movzx ex, byte1 ;CX = 009Bh
MOVSX 指令
MOVSX 指令(进行符号扩展并传送)将源操作数内容复制到目的操作数,并把目的操作数符号扩展到 16 位或 32 位。这条指令只用于有符号整数,有三种不同的形式:
MOVSX reg32, reg/mem8
MOVSX reg32, reg/mem16
MOVSX reg16, reg/mem8
.data byteVal BYTE 10001111b .code movsx ax,byteVal ;AX = 1111111110001111b如下图所示,复制最低 8 位,同时,将源操作数的最高位复制到目的操作数高 8 位的每一位上。
如果一个十六进制常数的最大有效数字大于 7,那么它的最高位等于 1。如下例所示,传送到 BX 的十六进制数值为 A69B,因此,数字“A”就意味着最高位是 1。(A69B 前面的 0 是一种方便的表示法,用于防止汇编器将常数误认为标识符。)