assembly 如何有效地将整个数据段向右移动2个字节?

w6lpcovy  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(77)

我想将整个数据段向右移动2个字节,同时在nasm中优化大小
我最好的想法是:

std
    pusha
    push es
    push ds
    pop es
    mov si, bp
    lea cx, [bp+0x1]
    lea di, [bp+0x2]
    rep movsb
    pop es
    popa

字符串
但它需要17个字节。。

oxf4rvwz

oxf4rvwz1#

11字节

设置rep movsb的开销似乎不值得,所以让我们做一个简单的循环。

4 00000000 89EB                            mov bx, bp
     5 00000002 43                              inc bx
     6                                  again:
     7 00000003 4B                              dec bx
     8 00000004 8A07                            mov al, [bx]
     9 00000006 884702                          mov [bx+2], al
    10 00000009 75F8                            jnz again

字符串
在开始时笨拙的inc bx是为了避免off-by-one错误,因为我们必须复制bp+1字节。
如果不是因为dec没有设置进位标志,我们可以通过以下方式去掉一个字节:

4 00000000 89EB                            mov bx, bp
     5                                  again:
     6 00000002 8A07                            mov al, [bx]
     7 00000004 884702                          mov [bx+2], al
     8 00000007 4B                              dec bx
     9 00000008 72F8                            jnc again ; BUG


因此我们有效地将bx与-1而不是与0进行比较。但是,如果bp保证小于32 K,那么您可以使用jns again并减少到10个字节。
我还尝试了一些使用lodsb / mov [si+3], aldf=1的版本来一起执行加载和递减,但问题是,由于lodsb没有设置标志,我们需要像cmp si, -1这样的东西来检查循环终止,这又增加了三个字节。所以我不能得到比11更短的版本。

相关问题