assembly 交换数组内容时的效率

nbysray5  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(167)

我是汇编的新手,我正在尝试交换两个数组之间的内容。我目前有这段代码,经过测试,我已经验证了它的工作原理。但是,我想知道这是否是获得所需结果的最有效的方法,或者是否有其他更有效的解决方案?

arrW    WORD  100h, 200h, 300h
arrSW   SWORD  -140, 200, -300

mov ax, arrW
xchg ax, arrSW
xchg ax, arrW
mov ax, [arrW +2]
xchg ax, [arrSW +2]
xchg ax, [arrW +2]
mov ax, [arrW + 4]
xchg ax, [arrSW +4]
xchg ax, [arrW +4]
5gfr0r5j

5gfr0r5j1#

mov ax, arrW
xchg ax, arrSW
xchg ax, arrW
mov ax, [arrW +2]

第一个让我印象深刻的是第二个xchg。在下面的指令中,在加载AX之前加载AX寄存器是没有意义的。因此,第一个重写也使8086的速度提高了20%,它是:

mov  ax, [arrW]
xchg ax, [arrSW]
mov  [arrW], ax
mov  ax, [arrW + 2]
xchg ax, [arrSW + 2]
mov  [arrW + 2], ax
mov  ax, [arrW + 4]
xchg ax, [arrSW + 4]
mov  [arrW + 4], ax

避免使用xchg指令的解决方案在8086上不划算,但在x86上通常是可行的。例如,下一个代码片段在8086上运行速度慢10%:

mov  ax, [arrW]
mov  bx, [arrSW]
mov  [arrW], bx
mov  [arrSW], ax

循环无法击败当前展开的代码,但如果数组变得更大,那么它可能会像下面这样:

mov  cx, 3
 mov  si, OFFSET arrW
 mov  di, OFFSET arrSW
More:
 mov  ax, [si]
 mov  dx, [di]
 mov  [si], dx
 mov  [di], ax
 add  si, 2
 add  di, 2
 dec  cx
 jnz  More

如果数组 arrWarrSW 在内存中彼此跟随,则相同的循环最好写为:

mov  bx, OFFSET arrW
More:
 mov  ax, [bx]
 mov  dx, [bx + 6]
 mov  [bx], dx
 mov  [bx + 6], ax
 add  bx, 2
 cmp  bx, OFFSET arrSW
 jb   More

如果CPU支持32位寄存器,那么使用这些双字可以将所需的迭代次数减半。如果元素的计数是奇数,我们剥离一个字大小的交换:

mov  cx, 39
 mov  si, OFFSET arrW
 mov  di, OFFSET arrSW
 shr  cx, 1
 jnc  More             ; Count was even
 mov  ax, [si]
 mov  dx, [di]
 mov  [si], dx
 mov  [di], ax
 add  si, 2
 add  di, 2
More:
 mov  eax, [si]
 mov  edx, [di]
 mov  [si], edx
 mov  [di], eax
 add  si, 4
 add  di, 4
 dec  cx
 jnz  More

上面的代码在循环开始时剥离了一个字大小的交换。正如@PeterCordes在这个答案下面的注解中所写的,通常把剥离的交换放在最后更好(出于数据对齐的原因)。下一个是这个版本:

mov  cx, 39
 mov  si, OFFSET arrW
 mov  di, OFFSET arrSW
 shr  cx, 1            ; -> CF is set if count is odd
 jz   Next             \
More:                   |
 mov  eax, [si]         |
 mov  edx, [di]         |
 mov  [si], edx         |
 mov  [di], eax         | Nothing changes the CF
 lea  si, [si + 4]      |
 lea  di, [di + 4]      |
 dec  cx                |
 jnz  More              |
Next:                  /
 jnc  Done             ; (*) Count was even
 mov  ax, [si]
 mov  dx, [di]
 mov  [si], dx
 mov  [di], ax
Done:

相关问题