首页 > 解决方案 > 您将如何编辑它以使数组移动 2 个位置?前任。最终数组是 30, 40,10, 20

问题描述

想要将数组移动 2 的 DWORD 变量,以便最终数组为 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

标签: assemblyx86masm

解决方案


您正在写入一个单独的目的地,因此阅读和写作之间没有重叠。这使它变得非常简单:您从一个数组的第一个到最后一个循环,然后从另一个数组的中间开始进行换行。

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

或者将循环拆分为 2 块:从 src 的中间到结尾,然后从开头到中间。

您甚至可以rep movsd为此使用两次而不是循环,edi保持不变以继续附加目标,但重置esi为从源的开头读取。(如果您不打算使用 SIMD 向量,rep movsd则对于可能 10 个或更多元素的一次 4 字节复制循环要快。或者使用慢速英特尔loop指令,收支平衡点甚至更低。)

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


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


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

arrayType DWORD TYPE array看起来是个坏主意。 TYPE array是汇编时间常数;您不想将其存储在内存中并将其作为数据加载,只需将其用作您正在使用的立即数ADD ESI, TYPE array

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


推荐阅读