我正在实现一个简单的汇编函数,该函数通过c中的程序调用,以计算32位数组奇数位置中有多少1个。传递给函数的第一个参数是指向数组的指针,第二个参数是元素的数量。我不明白它到底是怎么回事。
//汇编代码
.globl ones_in_odds
.type ones_in_odds,@function
ones_in_odds:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%ecx
movl 12(%ebp),%esi
#xorl %edi,%edi
xorl %eax,%eax
subl $-1,%esi
startloop:
cmpl $0,%esi
jl endloop
movl (%ecx,%esi,4),%edx
xorl %edi,%edi
innerloop:
cmpl $16,%edi
jg startloop
shrl %edx
shrl %edx
adcl $00,%eax
incl %edi
jmp innerloop
decl %esi
jmp startloop
endloop:
movl %ebp,%esp
popl %ebp
ret
// C代码
#include <stdio.h>
#define DIM 5
int ones_in_odds(int *,size_t);
int main(){
int array[DIM] = {1,3,4,5,6};
int one = ones_in_odds(array,DIM);
printf("Il numero di 1 nelle posizioni dispari e' %d\n",one);
return 0;
}
答案 0 :(得分:1)
将 1添加到ESI
:
subl $-1,%esi
就像术语ESI = ESI - (-1)
一样。您希望将项目(DIM
)的计数转换为array
中最后一项的索引。因此,必须将计数减1或加(-1)。但是,您不需要在此处进行此转换。删除该行。
因为
jg startloop
您未达到decl %esi
,因此永远不会遇到中断条件jl endloop
。
将decl %esi
移至startloop
的开头,您也可以解决上面的转换问题。
正如@Jester提到的那样,你必须遵循C calling convention,因为汇编程序是C程序的一个功能。该函数允许更改EAX
,ECX
和EDX
(“调用者已保存”)并且必须更改所有其他寄存器(“被调用者保存”)。该函数更改ESI
和EDI
,但应该保持不变。所以在函数的开头推动它们并在结束时弹出它们。