assembly - 从内存中添加一个字节到 AX 寄存器

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

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

最佳答案

正如您所说,如果您可以假设一个 386 兼容的 CPU,一个不错的选择(尤其是对于现代 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 for mov reg, imm16),如果您无法完全避免归零指令。

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

正如 Raymond 所说,您可以选择任何其他寄存器,您知道其高半部分在函数的那个​​点为零。也许你可以 mov cx, 4 而不是 mov cl, 4 如果你之前碰巧需要 CL=4 来做其他事情,但到那时你已经完成了 CX你需要添加到 AX 中。 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,而不是其他寄存器,它可能无法收回成本。

关于assembly - 从内存中添加一个字节到 AX 寄存器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68263286/

相关文章:

c - 为什么在 MASM Assembly 中使用 FPU x87 指令集执行操作时会得到无意义的数字?

windows - MS 加载程序将 PE 文件的哪些部分映射到内存中?

assembly - 错误 : Operation size not specified - NASm

assembly - Linux和Windows 'INT'指令的区别

assembly - 两个整数的商不显示在汇编中

assembly - 从寄存器中减去变量?错误 A2022 : instruction operands must be the same size

winapi - 如何在 MASM 中为一个项目编写和组合多个源文件?

assembly - 我试图在 AAM 指令之后使用 AX 中存储的值将其除以 2,为什么它不适用于 2 位数字输出?

assembly - 寄存器寻址模式 vs 直接寻址模式

visual-studio - 在 Visual Studio 中从 asm 调用 C 标准库函数