您将如何编辑它,以便将数组移动2个位置?例如最终数组为30、40、10、20

问题描述 投票:1回答:1

想要将数组移动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
assembly x86 masm
1个回答
0
投票

您正在写信给一个单独的目的地,因此读和写之间没有重叠。这非常简单:您可以从一个数组的第一个循环到最后一个循环,然后从另一个数组的中间开始环绕。

例如从目标的第一个元素开始,并使用分支有条件地从src指针中减去长度(以字节为单位)。 (与cmov相比,分支是一个不错的选择,因为它只会出现一次;每隔一次,您只会正常循环一次。)

或将循环拆分为两个块:从src的中间到末尾,然后从开始到中间。

您甚至可以为此使用rep movsd两次而不是循环,不修改edi以保持附加目标,但将esi重置为从源的开头读取。 (如果您不打算使用SIMD向量,则rep movsd的速度可能比一次4字节的复制循环快10个或更多元素。或者使用Intel慢速执行loop指令,盈亏平衡点甚至更低。)

对于固定大小的问题,您当然可以将整个内容加载到4个寄存器中,或者使用SSE2movdqu-load /pshufd/movdqu-store来对16字节SIMD向量的dword块进行混洗。


[如果必须执行此操作,就地旋转(更新一个数组而不是制作修改的副本),则可以使用几个暂存寄存器来处理可变长度的“旋转2个位置”部分的硬编码,以处理写入和写入之间的重叠。阅读。


我不打算发布代码,因为这看起来像是家庭作业,如果不解决它就不能显示示例。

但是arrayType DWORD TYPE array似乎是个坏主意。 TYPE array是一个汇编时间常数;您不想将其存储在内存中并作为数据加载,只需像使用ADD ESI, TYPE array

一样立即使用它即可

lastElement DWORD ?也未使用,这再次是一件好事。使用寄存器(直到用完为止)来存储暂存空间的单字块。

© www.soinside.com 2019 - 2024. All rights reserved.