Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 装配中的阶乘函数_C_Assembly - Fatal编程技术网

C 装配中的阶乘函数

C 装配中的阶乘函数,c,assembly,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; } 我一直收到分段错误,我不知道为什么…有人能帮我吗?这一行的偏移量可能是错误的: movl

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

在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;

    }

我一直收到分段错误,我不知道为什么…有人能帮我吗?

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

movl    4(%ebp),%edx
堆栈的上一个值为
%ebp
,并且返回地址已经存在,因此偏移量必须大于4


我建议使用调试器单步执行汇编代码,并确保所有寄存器值都是您期望的值。除非保存并还原其值,否则跨调用注册的
%edx也会有问题。

此行的偏移量可能错误:

movl    4(%ebp),%edx
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
堆栈的上一个值为
%ebp
,并且返回地址已经存在,因此偏移量必须大于4

我建议使用调试器单步执行汇编代码,并确保所有寄存器值都是您期望的值。除非您也保存并还原它的值,否则跨调用注册
%edx
也会有问题

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函数assemblyish样式可能会有所帮助:

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;
}
重写C函数assemblyish样式可能会有所帮助:

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;
}

为什么要递归计算阶乘?你想过循环吗?@ymorenz呃,这是什么ASM编译器?@Link这是GAS,主要由Linux使用。你为什么递归计算阶乘?你想过循环吗?@ymorenz,这是什么ASM编译器?@Link这是GAS,主要由Linux使用乘法的结果将是EDX:EAX,而不仅仅是EAX@coolbartek查阅CPU手册。具有2个操作数的IMUL与具有1个操作数的MUL或IMUL的工作方式不同。引号:
imulr32,r/m32:双字寄存器← 双字寄存器∗ r/m32。
您所说的对具有1个操作数的IMUL有效,请引用手册中的同一页:
IMUL r/m32:EDX:EAX← EAX∗ r/m32.
你说得对,谢谢你指出这一点,这听起来像是大多数操作的溢出though@coolbartek嗯,在C和C++中有大量的溢出,其中代码> int <代码> *>代码> int >代码>产生<代码> int <代码>乘法的结果将是EDX:EAX,而不仅仅是EAX@coolbartek查阅CPU手册。具有2个操作数的IMUL与具有1个操作数的MUL或IMUL的工作方式不同。引号:
imulr32,r/m32:双字寄存器← 双字寄存器∗ r/m32。
您所说的对具有1个操作数的IMUL有效,请引用手册中的同一页:
IMUL r/m32:EDX:EAX← EAX∗ r/m32.
你说得对,谢谢你指出这一点,这听起来像是大多数操作的溢出though@coolbartek嗯,在C和C++中有大量的溢出,其中代码> int <代码> *>代码> int >代码>产生<代码> int <代码>