装配中的因子功能

时间:2012-09-29 21:13:59

标签: c assembly

所以我试图在汇编程序中创建一个阶乘函数

在c:

 #include<stdio.h>



int fat (int n) 
{
      if (n==0) return 1;
      else return n*fat(n-1);
}

    int main (void){

    printf("%d\n", fat(4));
       return 0;

    }

在汇编中:

.text

.global    fat
fat:push    %ebp   
    mov    %esp, %ebp
    movl    $1,%eax
    movl    4(%ebp),%edx

LOOP:cmp    $0,%edx
    je FIM
    sub    $1,%edx
    push    %edx
    call    fat
    imul    %edx,%eax

FIM:mov    %ebp, %esp
    pop    %ebp
    ret

我一直得到分段错误错误,我不知道为什么......有人可以帮助我吗?

2 个答案:

答案 0 :(得分:2)

这一行的偏移可能是错误的:

movl    4(%ebp),%edx

堆栈的前一个值为%ebp且返回地址已经存在,因此您的偏移量必须大于4。

我建议使用调试器逐步调试汇编代码,并确保所有寄存器值都与您期望的完全相同。除非您保存并恢复其值,否则您在调用%edx注册时也会遇到问题。

答案 1 :(得分:1)

fat:push    %ebp   
    mov    %esp, %ebp
    movl    $1,%eax
    movl    4(%ebp),%edx /* Must be 8(%ebp) because of the return address! */

LOOP:cmp    $0,%edx
    je FIM
    sub    $1,%edx
    push    %edx
    call    fat /* The call to fat() just trashed edx, oops. Gotta save/restore it! */
    imul    %edx,%eax /* The result will be in edx, but you need to return it in eax! */
    /* Why isn't "push %edx" compensated here with "pop" or "addl $4,%esp"??? */
FIM:mov    %ebp, %esp
    pop    %ebp
    ret

重写你的C函数,装配风格可能会有所帮助:

int fat (int n) 
{
    int eax, edx, savedEdx;

    eax = 1;
    edx = n; /* n = %8(%ebp) */
    if (edx == 0)
      goto done;

    savedEdx = edx; /* can do this with pushl %edx */
    --edx;
    eax = fat(edx); /* pushl %edx; call fat; addl $4, %esp or popl %edx */
    edx = savedEdx; /* popl %edx */

    eax *= edx; /* can do this with imul %edx */

done:
    return eax;
}