c++ - 多个数组操作

标签 c++ arrays assembly vector

对于我的项目,我需要从文件中获取一个 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 中的元素之间的差异。(需要为2th3th 两个数组的值。然后我需要对 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/

相关文章:

c++ - 在 Visual Studio 4.0 中使用标准模板库

java - 如何将数组列表的元素添加到一起

c++ - 如何将 std::array 转换为一个点?

java - 如何将项目动态添加到 Java 数组?

c - 如何设置异常发生时的回调函数?

c++ - 在 std::strcpy 中使用 char*

c# - 什么是C# 等同于C++ STL 填充方法

c++ - 如何在C++ 11中的类中声明n个字符串的 vector

.s文件可以直接执行吗?

c - 如何使ARM1136JFS (ARM v6) MMU在物理地址空间和虚拟地址空间之间有一对一的映射?