MASM 汇编将 8 位寄存器移动到 16 位寄存器(即 mov cx, ch)
MASM Assembly move 8 bit register to the 16 bit register (ie. mov cx, ch)
我决定学习一门汇编语言。我正在使用 this 8086 tutorial。在底部,练习是找出一些指令中的错误,其中之一是
mov cx, ch
我在 SO 上发现了一些类似的问题,解释了如何实现它,但现在我想知道 为什么禁止此操作?
假设我在 CH 中有 10d = 00001010b 并想将其放入 CL 并同时擦除 CH。 mov cx, ch
似乎是这样做的,因为它将 10d 显示为 16bit 00000000 00001010 并将其分别放入 CH 和 CL(整个 CX)
它有什么问题,为什么给定的教程要求找出这个表达式中的错误?
问题是,您正试图将 8 位寄存器 ch
的内容移动到 16 位寄存器 cx
中。你不能那样做,因为寄存器的大小不同。
所以我猜您会收到类似 "invalid combination of opcode and operands" 的错误消息。
p.s:交换了上面的8和16;声明保持不变。例如检查 this overview。如您所见,没有定义不同寄存器大小的组合。这意味着不存在任何表示 mov cx, ch
.
的 OPcode
mov
指令用于在相同大小的操作数之间移动。您想要的是 将 8 位 ch
扩展 为 16 位 cx
。有两条指令可用于该目的:
movzx cx,ch ; zero-extends ch into cx. the upper byte of cx will be filled with zeroes
movsx cx,ch ; sign-extends ch into cx. the upper byte of cx will be filled with the most significant bit of ch
在这个特殊情况下完成同样事情的另一种方法是:
shr cx,8 ; zero-extend
sar cx,8 ; sign-extend
只需按照简单的说明进行操作
mov cl,ch ; copy high bits to low
xor ch,ch ; clear high-bits
在16位编程中很常见,只需要2个时钟周期。
使用movezx/movsx需要3个时钟周期。使用
movsx cx,ch
用于使用 sign-extension 和
将字节移动到字
movzx cx,ch
使用 zero-extension
将字节移动到字
您想将 CH
的内容移动到 8086 上的 CX
。
在较新的处理器上,例如 80286,您可以将 CX
的值右移 8 个位置,有或没有符号复制:
; zero extend ch into cx
shr cx,8
; sign extend ch into cx
sar cx,8
这些指令在 8088 或 8086 上不可用。您必须使用 CL
来指定移位计数:
; zero extend ch into cx
mov cl,8
shr cx,cl
; sign extend ch into cx
mov cl,8
sar cx,cl
但是这种方法非常慢,因为移动可变数量的位置需要每个位置多个周期。
这是一个更快的方法:
; zero extend ch into cx
mov cl,ch
xor ch,ch
; sign extend ch into cx
mov cl,ch
neg ch ; set the carry flag if ch is negative
sbb ch,ch ; set all bits if ch was negative, clear them otherwise
如果你能销毁 AX,你可以使用为此设计的 cbw
来节省代码大小。在原始的 8086,尤其是 8088 上,小 = 快,因为取码是一个主要瓶颈。不过,在现代 x86 上情况并非如此。
; sign extend ch into ax
mov al, ch
cbw ; sign-extend AL into AX
; optionally move back to cx
xchg cx, ax ; smaller than mov cx, ax
为了避免破坏 AX,您可以 mov cl,ch
; xchg ax,cx
; cbw
并停在那里,或者做最后的 xchg ax,cx
将 CH 符号扩展到 CX 并恢复其他所有内容。 xchg
with AX 是 1 字节指令,cbw
和 cwd
也是(将 AX 扩展为 DX:AX,例如在 16 位 idiv
之前)
cbw
与 386 movsx ax, al
.
完全相同
我决定学习一门汇编语言。我正在使用 this 8086 tutorial。在底部,练习是找出一些指令中的错误,其中之一是
mov cx, ch
我在 SO 上发现了一些类似的问题,解释了如何实现它,但现在我想知道 为什么禁止此操作?
假设我在 CH 中有 10d = 00001010b 并想将其放入 CL 并同时擦除 CH。 mov cx, ch
似乎是这样做的,因为它将 10d 显示为 16bit 00000000 00001010 并将其分别放入 CH 和 CL(整个 CX)
它有什么问题,为什么给定的教程要求找出这个表达式中的错误?
问题是,您正试图将 8 位寄存器 ch
的内容移动到 16 位寄存器 cx
中。你不能那样做,因为寄存器的大小不同。
所以我猜您会收到类似 "invalid combination of opcode and operands" 的错误消息。
p.s:交换了上面的8和16;声明保持不变。例如检查 this overview。如您所见,没有定义不同寄存器大小的组合。这意味着不存在任何表示 mov cx, ch
.
mov
指令用于在相同大小的操作数之间移动。您想要的是 将 8 位 ch
扩展 为 16 位 cx
。有两条指令可用于该目的:
movzx cx,ch ; zero-extends ch into cx. the upper byte of cx will be filled with zeroes
movsx cx,ch ; sign-extends ch into cx. the upper byte of cx will be filled with the most significant bit of ch
在这个特殊情况下完成同样事情的另一种方法是:
shr cx,8 ; zero-extend
sar cx,8 ; sign-extend
只需按照简单的说明进行操作
mov cl,ch ; copy high bits to low
xor ch,ch ; clear high-bits
在16位编程中很常见,只需要2个时钟周期。
使用movezx/movsx需要3个时钟周期。使用
movsx cx,ch
用于使用 sign-extension 和
将字节移动到字movzx cx,ch
使用 zero-extension
将字节移动到字您想将 CH
的内容移动到 8086 上的 CX
。
在较新的处理器上,例如 80286,您可以将 CX
的值右移 8 个位置,有或没有符号复制:
; zero extend ch into cx
shr cx,8
; sign extend ch into cx
sar cx,8
这些指令在 8088 或 8086 上不可用。您必须使用 CL
来指定移位计数:
; zero extend ch into cx
mov cl,8
shr cx,cl
; sign extend ch into cx
mov cl,8
sar cx,cl
但是这种方法非常慢,因为移动可变数量的位置需要每个位置多个周期。
这是一个更快的方法:
; zero extend ch into cx
mov cl,ch
xor ch,ch
; sign extend ch into cx
mov cl,ch
neg ch ; set the carry flag if ch is negative
sbb ch,ch ; set all bits if ch was negative, clear them otherwise
如果你能销毁 AX,你可以使用为此设计的 cbw
来节省代码大小。在原始的 8086,尤其是 8088 上,小 = 快,因为取码是一个主要瓶颈。不过,在现代 x86 上情况并非如此。
; sign extend ch into ax
mov al, ch
cbw ; sign-extend AL into AX
; optionally move back to cx
xchg cx, ax ; smaller than mov cx, ax
为了避免破坏 AX,您可以 mov cl,ch
; xchg ax,cx
; cbw
并停在那里,或者做最后的 xchg ax,cx
将 CH 符号扩展到 CX 并恢复其他所有内容。 xchg
with AX 是 1 字节指令,cbw
和 cwd
也是(将 AX 扩展为 DX:AX,例如在 16 位 idiv
之前)
cbw
与 386 movsx ax, al
.