【问题标题】:MOV 8 bit to 16 bit register (al to bx)MOV 8 位到 16 位寄存器(al 到 bx)
【发布时间】:2019-11-08 13:54:42
【问题描述】:

如何解决将 8 位值移动到 BX 寄存器(16 位)的问题?

mov al, 10h
mov bx, al

为此我得到:

operands do not match: 16 bit and 8 bit register 

【问题讨论】:

  • 您需要转换大小或依赖部分寄存器。例如。 movzx bx, almovsx bx, alxor bh, bh; mov bl, al
  • 或者更好,movzx ebx, al 写入完整的寄存器,而不是只写入 16 位的部分寄存器。
  • @PeterCordes 我们不知道这是 16 位代码还是 32 位代码:)
  • @Jester:啊。鉴于 OP 报告“不工作”,这可能是 emu8086 或其他一些遗留问题。幸运的是,Fuz 回答了这两种情况。
  • 该错误信息具体是emu8086生成的错误,所以环境上没有什么疑问。我已经更新了标签。

标签: assembly x86-16 emu8086 sign-extension zero-extension


【解决方案1】:

答案取决于您是要对值进行零扩展还是符号扩展,以及您是否可以使用以 80386 开头的可用指令。为了获得更好的性能,如果movzxmovsx 可用。

8086 或 80286 上的零扩展

将上半部分归零,然后移至下半部分。

xor bh, bh
mov bl, al

(或者等效地,在一些后来的 CPU 上更有效,xor bx, bx 在替换低 8 之前将整个 16 位归零。)

在 8086 或 80286 上扩展符号

如果没有movsx,您可能想要使用仅适用于ALcbw -> AX。最简单的方法是在复制到BX 之前覆盖AH,因为您的值已经在AL 中。

 cbw               ; AH = 0 or 0xFF according to top bit of AL
 mov  bx, ax

如果你想保留AH,你可以先复制旧的AX,然后在cbw之后交换:

 mov  bx, ax      ; save the old AH (and AL)
 cbw              ; sign-extend AL into AX
 xchg bx, ax      ; BX = sign-extended result, restore original AX

在 8086 上保存指令可能涉及计划您在哪个寄存器中保留的内容,以便它已经在正确的位置,以便使用隐式寄存器的指令,如 cbwmul。到 386 年,英特尔添加了其中一些可用于任何寄存器的版本。


80386 或更高版本的零扩展

使用movzx

movzx bx, al

为了获得最佳性能,零一直扩展到 32 位。

movzx ebx, al

在 80386 或更高版本上扩展符号

使用movsx,类似于cbw,但适用于任何dst、src,甚至包括内存源。

movsx bx, al

如果可能,将符号一直扩展到 32 位以获得更好的性能。

movsx ebx, al

其他方法:也可以使用neg/sbb 设置上半部分,符号或零扩展的算术移位或逻辑移位也是可能的。 (特别是如果您的值始于 AH 之类的寄存器)。见MASM Assembly move 8 bit register to the 16 bit register (ie. mov cx, ch)

【讨论】:

  • 如果你能摧毁AH,你可以在8086上cbw/mov bx, ax
  • 如果在某些现代 CPU 上运行,您的编辑会降低代码的效率。 xor bx,bx first 可能比 xor bh,bh 好。它仍然对旧值有错误的依赖性,因为它不会写入在 16 位模式下可访问的完整 32 位,但在 P6 系列上,当您读取完整的 bx 时,它可能会避免部分 reg 停顿。 (不确定 16 位寄存器是否如此)。编写 BH 还介绍了 SnB-family 上的 BH-merging。我明白你的观点,不过,有些人可能更容易理解分别写上/下半部分。
  • @PeterCordes 我知道。鉴于 OP 显然不是在对性能敏感的环境中进行编程,因此教育部分在这里更为重要。
  • 等一下,test / sbb 有用吗? test 总是清除 CF。我认为您需要 cmp al, 80h + cmc 或根据 AL 的符号位设置 CF 的东西。或者 CBW 周围的一些单字节 xchg ax,bx 的东西。 (我在编辑时一直在评论这个块;这让我想到了 SBB 实际读取的标志)
  • mov bx, ax / cbw / xchg bx, ax 是避免破坏 AH 的最小代码大小方法,并且在现代 CPU(尤其是在 Broadwell 之前的 Intel其中 SBB 为 2 微秒)。不得不让它在我的脑海中反弹一段时间才能想到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
  • 2017-04-14
  • 2020-11-21
相关资源
最近更新 更多