微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将内存中的一个字节添加到 AX 寄存器

如何解决将内存中的一个字节添加到 AX 寄存器

我目前正在尝试弄清楚如何将指针寄存器 SI 指向的内存中的第一个字节添加AX 寄存器的当前内容中。

因此,如果 SI 包含某个地址,并且该地址的内存中的值为:00 和 01,我希望仅将 00 添加AX 寄存器中。

我不喜欢汇编的自己尝试的第一条指令是 add ax,byte ptr [SI] 但当然没有骰子,因为我正在尝试添加不同大小的操作数。

我目前的解决方法

mov dx,0000h             ;empty the contents of dx
mov dl,byte ptr [si]     ;get the value of the first byte in a register
add ax,dx                ;perform the originally desired addition

但这是非常浪费的,并且真的损害了我执行的指令计数(这是运行多次的子程序的一部分)。

我只能使用 8086 指令集,因此 this question/answer by Peter Cordes 建议使用 movzx 来压缩我的前两行,但不幸的是不可行。

解决方法

如您所说,如果您可以假设 CPU 兼容 386,那么一个不错的选择(尤其是对于现代 CPU)是 movzx dx,byte ptr [mem] / add ax,dx。如果没有,我想我们可以假装我们正在调整一个真正的 8086,where code size in bytes is often more important than instruction count。 (特别是在 8088 上,它的 8 位总线。)所以你肯定想使用 xor dx,dx 来归零 DX(2 个字节而不是 3 个用于 mov reg,imm16),如果你不能避免归零指令一共。

从任何循环中提升 DX(或 DH)的归零,因此您只需 mov dl,[mem] / add ax,dx。如果函数只执行一次,您可能需要(手动) 在循环调用它的调用站点中内联该函数,如果它足够小以使其有意义。或者选择一个寄存器,调用者负责将上半部分为零。

正如 Raymond 所说,您可以选择任何其他寄存器,在您的函数中,您知道其高半部分在该点为零。也许您可以用 mov cx,4 代替 mov cl,4,如果您之前碰巧需要 CL=4 用于其他东西,但是当您需要添加到 AX 时,您已经完成了 CX。 mov cx,4 仅长 1 个字节,因此您只需 1 个额外字节的代码大小即可将 CH 清零。 (相对于 xor cx,cx 花费 2 个字节)


另一个选项是字节添加/adc,但这对于代码大小来说并不理想。 (或在更高版本的 CPU 上的性能。)

  add al,[mem]      ; 2 bytes + extra depending on addr mode
  adc ah,0          ; 3 bytes

所以这比如果你已经有一个备用的高位零寄存器多 1 个字节:

  mov  dl,[mem]     ; 2 bytes (+ optional displacement)
  add  ax,dx        ; 2 bytes

但从好的方面来说,add/adc 根本不需要任何额外的寄存器。


使用 SI 中的指针,如果您真的要优化代码大小,那么寻找利用 lodsb 的方法是值得的。这样做 mov al,[si] / inc si (或者如果 DF=1 则改为 dec si),但不会影响 FLAGS。所以你想添加到不同的寄存器中。

xchg ax,reg 只有 1 个字节,但如果您需要两次交换,如果您实际上必须返回 AX 而不是其他寄存器,则可能无法收回成本。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。