assembly - 您将如何编辑它以使数组移动 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
解决方案
您正在写入一个单独的目的地,因此阅读和写作之间没有重叠。这使它变得非常简单:您从一个数组的第一个到最后一个循环,然后从另一个数组的中间开始进行换行。
例如,从目标的第一个元素开始,并使用分支有条件地从 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 ?
也未使用,这又是一件好事。对暂存空间的单双字块使用寄存器(直到用完为止)。
推荐阅读
- javascript - 无法显示来自 API 的数据
- apache-kafka - log.cleaner.dedupe.buffer.size 和 log.cleaner.io.buffer.size 有什么区别?
- python - 用 matplotlib.animation 制作动画
- javascript - 使用 Redux 表单上传文件
- kotlin - 何时使用 Kotlin 暂停关键字?
- python-3.x - How do I execute the following command using subprocess?
- image - 快速选择工具算法
- c# - Visual Studio 在调试时向 Web 应用添加虚拟路径
- python - 使用 pandas 合并保留下 n 行和前 k 行
- linux - 使用 incrontab mv 文件导致 0 字节文件