我想将数组移位一个DWORD变量2,这样最终的数组就是30,40,10,20
我想支持可变长度的数组
.data
array DWORD 10,20,30,40
arrayType DWORD TYPE array
newArray DWORD LENGTHOF array DUP(?)
lastElement DWORD ?
.code
main PROC
;Get first element address in ESI
MOV ESI, OFFSET array
;Get address of next element in EDI
MOV EDI, OFFSET newArray
ADD EDI, TYPE newArray
;set loop count into ecx
mov ECX, LENGTHOF array
L2:
MOV EAX, [ESI]
MOV [EDI], EAX
ADD ESI, TYPE array
ADD EDI, TYPE array
LOOP L2
;set last element from array in newArray first position
MOV EDI,OFFSET newArray
MOV EAX, [ESI]
MOV [EDI], EAX
发布于 2019-10-25 13:46:33
你正在写一个单独的目的地,所以在读和写之间没有重叠。这使得它变得非常简单:从一个数组的第一个循环到最后一个数组,然后从另一个数组的中间开始换行。
例如,从目的地的第一个元素开始,并使用分支有条件地从src指针减去长度(以字节为单位)。(与cmov相比,分支是一个很好的选择,因为它只会为真一次;每隔一次您就会正常地循环一次)。
或者拆分你的循环,复制成两个块:从src的中间到结尾,然后从开始到中间。
您甚至可以对此使用两次rep movsd
,而不是循环,保留edi
不变以继续附加目标,但将esi
重置为从源开始读取。(如果您不打算使用单指令多数据向量,对于10个或更多元素,rep movsd
比一次4字节的复制循环更快。或者使用slow-on-Intel loop
指令,盈亏平衡点更低。)
对于固定大小的问题,您当然可以将整个内容加载到4个寄存器中,或者使用SSE2 movdqu
-load / pshufd
/ movdqu
-store来混洗16字节SIMD向量的双字块。
如果你必须就地旋转(更新一个数组,而不是制作一个修改过的副本),你可以使用几个临时寄存器在可变长度上硬编码“旋转2个位置”部分,以处理写入和读取之间的重叠。
我不打算发布代码,因为这看起来像家庭作业,如果不解决它,我就不能展示一个例子。
但是arrayType DWORD TYPE array
看起来不是个好主意。TYPE array
是一个汇编时间常量;您不希望将其存储在内存中并将其作为数据加载,只需像使用ADD ESI, TYPE array
一样将其用作立即数即可
lastElement DWORD ?
也未被使用,这也是一件好事。使用寄存器(直到用完为止)作为单字块的暂存空间。
https://stackoverflow.com/questions/58552116
复制相似问题