为什么即使你自己想要从栈中取出参数,也可以使用内联asm?要么让编译器给你参数(所以它在内联之后仍然有效),或者在单独的文件中写入纯粹的asm。
下面是你写的功能很好的一个版本。请注意缩进和更高效的代码(分支结构,并加载到寄存器中,而不是在内存中进行比较,然后用作添加的内存操作数。如果预期条件不太可能,则带有内存的test
或cmp
操作将使感,虽然)。
int sum(const int *a, int n)
{
int S;
_asm {
mov ecx, n
xor eax,eax // Sum = 0
test ecx,ecx
jz .early_out // n==0 case
mov esi, a
lea edi, [esi + 4*edi] // end pointer
.sum_loop:
// Assume even/odd is unpredictable, so do it branchlessly:
xor ecx,ecx
mov edx, [esi] // lodsd could be used here (to load eax: keep the total somewhere else)
test edx, 1 // ZF cleared for odd numbers only
cmovz ecx, edx // ecx=even:a[i] odd:0
add eax, ecx // add zero or a[i]
add esi, 4
cmp esi, edi // pointer < end pointer
jb .sum_loop
.early_out:
mov S, eax // MSVC inline asm is super dump: we can't just tell it the result is in eax
}
return S;
}
用树枝,简单的方法就是
.sum_loop:
mov edx, [esi]
test edx, 1
jnz .odd // conditionally skip the add
add eax, edx
.odd:
add esi, 4
cmp esi, edi // pointer < end pointer
jb .sum_loop
你原来的分支结构(复制回路奇/偶分支的尾部)是对于某些情况有用的技术,但不是在这里它们在加入总量后再次相同。
在asm中,使用底部的条件分支编写循环。在进入循环之前检查暗示零迭代的条件。你不希望一个未采取的cmp/jcc 和采取无条件分支。
lodsd
与英特尔的mov eax, [esi]
/add esi, 4
一样有效,从Haswell开始。它在早期的英特尔和AMD上是3个微软,所以它以牺牲速度为代价来节省代码大小。
查看x86的指南和东西。
定义“不工作”。它在做什么,这与你所期望的有什么不同? – davmac
另请注意,'和[eax + ecx * 4],1'会破坏您的输入数组。这是打算吗? – davmac