Assembly 使用间接递归的_-cdecl问题

Assembly 使用间接递归的_-cdecl问题,assembly,cdecl,Assembly,Cdecl,我写了一个阶乘计算程序,一直到最后的计算。在计算\u multiply\u fact中的阶乘值时,基指针最终指向一个随机值。我做错了什么 召唤 push n call _factorial add esp, 4 程序 _factorial: push ebp ;save base pointer mov ebp, esp ;set up new base pointer mov ebx, 8[ebp] cmp ebx, 1

我写了一个阶乘计算程序,一直到最后的计算。在计算
\u multiply\u fact
中的阶乘值时,基指针最终指向一个随机值。我做错了什么

召唤

push n
call _factorial
add esp, 4
程序

_factorial:
    push ebp            ;save base pointer
    mov ebp, esp        ;set up new base pointer
    mov ebx, 8[ebp]

    cmp ebx, 1          ;while n > 0
    jg _multiply_fact   ;decrement n
    mov eax, 1          ;if n == 0 ret 1
    pop ebp
    ret                 ;return to multipy_fact for calculation

_multiply_fact:
    pop ebp     
    push ebp
    mov ebp, esp
    mov ebx, 8[ebp]

    dec ebx                 ;decrements n-1 times
    push ebx
    call _factorial 

    inc ebx                 
    mul ebx                 ;recursively multiplies eax * (n+1)
    pop ebp
    ret

好的,在进行了更多的故障排除之后,我发现这个错误是因为我忘了包括

add esp, 4

正如您所说,在我在_multiply _fact过程中调用_factorial之后,阻止它工作的错误是在递归调用之后没有修复堆栈。但这并不是唯一的错误

\u multiply\u fact
实际上不是一个函数。它只是
\u factorial
代码的一部分,当您不提前退出
n0)时,它会运行。请注意,dec没有设置CF,所以如果您想将其转换为无符号,只需使用jnz而不是ja
;; 基本情况
mov-eax,1;如果(n)
global _factorial
_factorial:
    ; one arg:  int n

    push  ebp
    mov   ebp, esp        ; make a stack frame

    mov   edx, [ebp + 8]  ; load first arg into a scratch reg
    dec   edx
    jg .multiply_fact     ; if ((n-1) > 0).  Note that dec doesn't set CF, so just use jnz instead of ja if you want to convert this to unsigned

    ;; base case
    mov   eax, 1          ;if (n <= 1) ret 1
    pop   ebp
    ret

.multiply_fact:   ; not a separate function, still part of _factorial
                  ; in NASM, .labels are local labels that don't show up as symbols in the object file.  MASM uses something different.
    ; at this point:  edx = n-1

    push  edx
    call  _factorial     ; eax = fac(n-1)
    pop   edx            ; get n-1 back off the stack.  Taking advantage of extra knowledge of our own internals, since the ABI allows functions to clobber their args on the stack
    ; add esp, 4  not needed, because we popped instead

    inc   edx            ; undo the earlier dec before we pushed
    imul  eax, edx       ; n * fac(n-1).  2-arg imul runs faster
    pop ebp
    ret