【问题标题】:Adding a byte from memory to the AX register将内存中的一个字节添加到 AX 寄存器
【发布时间】:2021-07-06 00:42:26
【问题描述】:

我目前正试图弄清楚如何将指针寄存器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 压缩我的前两行很遗憾是不可行的。

【问题讨论】:

  • xor dx, dx 将是一个较短的编码。如果您必须完全减少指令数,则必须找到一些高 8 位已经为零的寄存器。也许有一个您没有使用的寄存器,您可以在程序的生命周期内将高 8 位保留为零。
  • 谢谢你,如果可行,我会尝试实施并关闭问题。
  • 似乎指令计数只减少了少量(讲师提供了一个驱动程序,该程序执行分级并计算作为该指标的一部分执行的指令)不幸的是,也是因为驱动程序(这是我的子例程 [callee] 的调用者er)我不确定在程序的生命周期内哪个寄存器可能是空的。感谢您的帮助 - 看来我必须查看我的决策逻辑以进一步减少计数。
  • 我认为我需要一个正式的答案来结束这个问题 - 我很乐意这样做,因为这确实帮助我减少了我提供的信息的指令数。

标签: assembly x86-16 masm micro-optimization zero-extension


【解决方案1】:

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

从任何循环中提升 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 中返回,而不是在其他一些寄存器中返回,则它可能不会自行支付。

【讨论】:

  • lodsb 指针递增或递减当然类似于dec siinc sisi 的影响。但它不会影响任何状态标志。所以它更类似于lea si, [si + 1]lea si, [si - 1]
  • @ecm:谢谢,忘了提到无标志部分。我认为“inc but without FLAGS”比涉及lea 的实际仿真更清晰,尤其是对于初学者而言。还有其他问答涉及lea,至少对于推送/弹出,可能还有lods 和其他人。
猜你喜欢
  • 2020-04-18
  • 1970-01-01
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 2021-09-19
  • 2018-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多