C 装配中的阶乘函数
所以我试图在汇编程序中创建一个阶乘函数 在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
#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 <代码>