我目前正在尝试弄清楚如何将指针寄存器 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/