You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C与NASM实现递归阶乘始终输出1的问题排查求助

阶乘程序输出始终为1的问题排查与修复

问题概述

用C编写输入输出逻辑,NASM汇编实现阶乘核心逻辑,但无论输入什么数字,输出结果始终为1。已尝试修改条件跳转指令、调整乘法顺序、初始化eax,问题未解决,编译时还收到警告。

核心错误原因

你完全搞错了C与汇编交互的参数传递规则:在x86的cdecl调用约定(gcc默认32位调用约定)中,函数参数是通过栈传递的,而非存在ecx寄存器里。你当前的汇编代码直接把ecx当作输入参数,但实际上ecx里根本不是用户输入的数值,导致无论输入什么,都会触发cmp ecx,1的分支,直接返回1。

修复方案

修正后的NASM汇编代码

section .text
    global factorial

factorial:
    ; 从栈中获取参数n:call指令会把返回地址压入栈,[esp+4]就是第一个参数
    mov ecx, [esp+4]

    ; Base case:n<=1时返回1
    cmp ecx, 1
    jle .base_case    

    ; 递归逻辑
    push ecx        ; 保存当前n到栈
    dec ecx         ; 计算n-1
    push ecx        ; 将n-1作为参数压栈,准备调用factorial
    call factorial  ; 递归调用,返回值存在eax中
    add esp, 4      ; cdecl约定:调用者负责清理参数栈(这里清理压入的n-1)
    pop ecx         ; 恢复之前保存的n
    imul eax, ecx   ; eax = factorial(n-1) * n

    ret

.base_case:
    mov eax, 1
    ret

代码说明

  1. 参数获取:通过[esp+4]读取第一个参数,符合cdecl调用约定的参数传递规则;
  2. 递归调用:递归时需要把n-1压入栈作为参数,调用完成后用add esp,4清理栈空间;
  3. 返回值:C约定函数返回值存在eax寄存器中,这部分你之前的逻辑是对的。

关于编译警告的说明

你遇到的警告大概率是调用约定不匹配或参数传递异常导致的(比如gcc检测到汇编函数的参数处理不符合C规范),这类警告必须重视——它直接指向程序逻辑的底层错误,不修复会导致程序行为完全不符合预期。修正参数传递逻辑后,警告应该会自动消失。

验证编译与运行

使用你原来的编译命令即可正常运行:

nasm -f elf RecurciveFactorial.asm && gcc -m32 -o RecurciveFactorial RecurciveFactorial.c RecurciveFactorial.o && ./RecurciveFactorial

内容的提问来源于stack exchange,提问作者X_Abhishek_X

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 03:42:46