【问题标题】:Count how many 1 there are in the odd positions of an array of 32-bit numbers计算一个 32 位数字数组的奇数位置有多少个 1
【发布时间】:2017-09-04 12:01:17
【问题描述】:

我正在实现一个通过 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;
}

【问题讨论】:

  • 永远无法到达decl %esi。学习使用调试器,并评论您的代码。 PS:esi是一个被调用者保存的寄存器。
  • 谢谢,我如何使用调试器进行组装?使用esi寄存器不是好事吗?我的书,“从头开始编程”,没有提及它。
  • 您使用与 C 相同的调试器。逐行执行代码,检查变量(寄存器)。你可以使用esi,但你必须根据标准调用约定为你的调用者保留它(如果你的代码是从C调用的,这很重要,就像这里的情况一样)。
  • 一切都清楚了,我该如何修复我的代码?

标签: c arrays assembly x86


【解决方案1】:

添加 1 到ESI

subl $-1,%esi

就像术语ESI = ESI - (-1)。您希望将项目的 count (DIM) 转换为 array 中最后一个项目的 index。因此,计数必须减 1 或加 (-1)。但是,您不需要在这个地方进行这种转换。删除该行。

因为

jg startloop

您没有到达decl %esi,因此将永远不会满足中断条件jl endloop

decl %esi移动到startloop的开头,你也解决了上面的转换问题。

正如@Jester 提到的,您必须遵循C calling convention,因为汇编过程是C 程序的函数。该函数允许更改EAXECXEDX(“调用者保存”)并且必须返回所有其他寄存器不变(“被调用者保存”)。该函数更改ESIEDI,但应将它们原样返回。所以在函数的开头push,最后pop。

【讨论】:

    猜你喜欢
    • 2011-02-25
    • 1970-01-01
    • 2021-12-30
    • 2021-01-19
    • 1970-01-01
    • 2022-11-10
    • 2018-08-20
    • 2023-03-10
    相关资源
    最近更新 更多