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,chxchg ax,cx; cbw 并停在那里,或者做最后的 xchg ax,cx 将 CH 符号扩展到 CX 并恢复其他所有内容。 xchg with AX 是 1 字节指令,cbwcwd 也是(将 AX 扩展为 DX:AX,例如在 16 位 idiv 之前)

cbw 与 386 movsx ax, al.

完全相同