对于我的项目,我需要从文件中获取一个 vector 数组,然后需要将它与两个 A 和 B vector 进行比较,并且需要找出 A 和 B 中的哪一个更接近我们从文件中读取的 vector 。
我已经完成了 C++ 部分(从文件等中获取 X 的值)
例如:对于X(1,3,5),A(2,4,6)(对于到 X 的距离是 (|2-1|+|4-3|+|6-5|)= 3) 然后我需要对 B 做同样的操作并找出哪个值更小(哪个表示更接近X vector )
基本上对于 3 个大小的数组,我需要找到 X 和 A 的第一个、第二个和第三个元素之间的差异 (然后需要它们总和的绝对值然后我需要为 B 执行此操作然后比较两个值)
但我真的被 assembly 部分困住了:
到目前为止,我知道要找到距离,我需要使用这段代码来找到绝对值,但在使用下面这段代码之前,我需要找到两个元素之间的差异然后应用此代码求出绝对值
这是寻找绝对值的代码片段,我不知道它是否有帮助:
mov ebx, eax ; move eax to ebx
neg eax ; eax = -eax
cmovl eax, ebx ; if negative move ebx back to eax
但我的主要问题是:我怎样才能从 X 和 A 中获取第一个元素,从而得到它们在 Assembly 中的元素之间的差异。(需要为2th 和 3th 两个数组的值。然后我需要对 X 和 B 执行相同的操作,但如果你向我展示 A,我确定我可以应用相同的算法对于乙
我的汇编函数的 C++ 原型(prototype)是这样的:
distance(int n, int * Xptr, int * Aptr, int * Bptr);
并将 A 和 B 定义为具有 3 个成员的数组。
最佳答案
您使用间接寻址访问数组。
像这样:
;ecx = number of items in the array
push ebx
push esi
push edi
xor ebx,ebx ;outcome is zero.
mov esi,Array1 ;esi = address of array1
mov edi,Array2 ;edi = address of array2
add esi,ecx ;esi = end of array
add edi,ecx ;edi = end of array
neg ecx ;start at the beginning of each array
jz done ;count is zero, nothing to do
loop: ;for (i=0;i<count;i++)
mov edx,[edi+ecx] ;edx = Array1[i] or Array1[start+length-count]
mov eax,[esi+ecx] ;ebx = Array2[i]
sub eax,edx ;calculate difference
cdq ;edx = eax < 0? -1:0
add eax, edx
xor eax, edx ;eax = abs(eax)
add ebx,eax
inc ecx ;i++
jnz loop
done:
mov eax,ebx
pop edi
pop esi
pop ebx
ret
让我带您了解代码。
我们从将总和设置为零并设置指向数组的指针开始。
然后我们取反计数并更新指向数组末尾的指针。
这个看似复杂的设置是一种速度黑客,它允许您从 -count 计数到零,同时不必保留额外的变量来跟踪数组索引。
然后我们做一些魔术来做腹肌,而不必做跳跃或有条件的 Action 。
你调用这个例程两次。一次获取 abs(A[]-X[])
并再次获取 abs(B[]-X[])
。
关于 abs 技巧,请参阅:https://www.strchr.com/optimized_abs_function
您必须进行一些更改以将其调整为您的调用约定。我将此作为练习留给读者。您可以调整代码以一次性完成所有比较,我也将其留给读者。
只是为了好玩,让我们把 abs 样本分开:
Alt-A cycles bytes Alt B cycles bytes
mov ebx, eax 0 2 cdq 1 1
neg eax 1 2 add eax,edx 1 2
cmovl eax, ebx 2 3 xor eax,edx 1 2
如您所见,两个样本之间的差别很小。我只是更喜欢 cdq 变体,因为它更优雅。
关于c++ - 多个数组操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44189935/