对于我的项目,我需要从文件中获取一个矢量数组,然后需要将它与两个A和B矢量进行比较,并且需要找到A和B中哪一个更靠近我们从文件中读取的矢量。
我已经完成了C ++部分(从文件等中获取X值)。
例如:对于 X(1,3,5), A(2,4,6)(表示到X的距离是(| 2-1 | + | 4-3 | + | 6-5 |)= 3 )然后我需要对B做相同的操作并找到哪个值较小(其中意味着更接近X矢量)
基本上对于3个大小的阵列,我需要找到X和A的第1,第2和第3个元素之间的区别 (然后需要它们的总和的绝对值然后我需要为B做这个,然后比较两个值)
但我真的坚持使用大会部分:
到目前为止,我知道找到距离我需要使用此代码来查找绝对值,但在下面使用此代码之前我需要找到两个元素之间的区别然后应用此代码来查找绝对值
以下是查找绝对值的代码片段我不知道是否有帮助:
mov ebx, eax ; move eax to ebx
neg eax ; eax = -eax
cmovl eax, ebx ; if negative move ebx back to eax
但是我的主要问题是:如何从X和A中获取第一个元素来获得它们在Assembly中的元素之间的差异。(需要这样做才能两个阵列的第二和第三值。然后我需要对X和B执行相同的操作但是如果你告诉我我确定我可以应用相同的算法对于B
我的C ++原型Assembly函数是这样的:
distance(int n, int * Xptr, int * Aptr, int * Bptr);
并将A和B定义为具有3个成员的数组。
答案 0 :(得分:0)
使用间接寻址访问数组。
像这样:
;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计数到零,同时不必保留额外的变量来跟踪数组索引。
然后我们做一些魔术来做一个abs而不必做跳跃或有条件的动作。
您将此例程调用两次。一旦获得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变种,因为它更优雅。