【问题标题】:Unhandled Exception: Recursive Factorial in assembly (MASM)未处理的异常:汇编中的递归阶乘 (MASM)
【发布时间】:2012-12-01 06:23:08
【问题描述】:

我用汇编语言 (MASM) 编写了一个程序,让学生练习计算组合。该程序递归地计算阶乘。我使用了一个称为组合的过程,它接收 n 和 r,然后得到 (n=r)!、n! 和 r!通过调用称为阶乘的过程。阶乘是递归的。

.data
n       DWORD   ?
r       DWORD   ?
result  DWORD   ?
answer            DWORD ?
divisor DWORD   ?

.code
MAIN    PROC

(一些初步的过程调用)

push OFFSET divisor     ;ebp+20
push n              ;ebp+16
push r              ;ebp+12
push OFFSET result      ;ebp+8
call    combinations

;*************************************************
; combinations calls factorial (3 times) to calculate n!, r!, and (n-r)!.
; combinations calculates n!/(r!(n-r)!) , and stores the value in result.
; receives:  accepts n and r by value and result by address.
; returns: none
; preconditions: none
; registers changed:  eax, ebx, edx
;*************************************************
combinations    PROC
push        ebp
mov     ebp,esp

mov     eax, [ebp+16]   ;find (n-r)!
sub     eax, [ebp+12]
mov     ebx, eax
push        ebx
call        factorial
pop     ebx
mov     edx,[ebp+20]    ;move (n-r)! into result
mov     [edx],eax

mov     ebx, [ebp+12]        ;find r!
push        ebx
call        factorial
pop     ebx

mov     edx,[ebp+20]
mov     ebx, [edx]
mul     ebx         ;r!*(n-r)!, store product in eax
mov     ebx, [ebp+20]
mov     [ebx], eax          ;store product in divisor variable

mov     ebx, [ebp+16]   ;find n!
push        ebx
call        factorial
pop     ebx
mov     edx,[ebp+20]            
mov     ebx,[edx]           ;move value of divisor into ebx

mov     edx, 0
div     ebx         ;divide n! by divisor (r!*(n-r)!)
mov     ebx, [ebp+8]
mov     [ebx],eax                 ;move quotient into result

pop     ebp
ret     16
combinations    ENDP

;*************************************************
; calculates factorial recursively
; receives: 
; returns: factorial solution in eax
; preconditions: none
; registers changed: eax
;*************************************************
factorial   PROC
mov eax,dword ptr [esp+4]
cmp eax,1
jle endRecursive
dec eax
push eax
call factorial
mov esi,dword ptr [esp+4]
mul esi
endRecursive:
    ret 4
factorial   ENDP

一切都按预期进行,我得到了所需的值。但是,当所有计算完成并且程序在组合过程结束时到达语句“ret 16”时,我得到以下异常:

Project.exe 中 0x76f915de 处未处理的异常:0xC0000005:访问冲突。

我已经通过调试器运行它并尝试在我计算错误的情况下更改 return 语句,但到目前为止我尝试过的任何方法都没有奏效。也许这是一个盯着这个太久的例子,但任何想法都会受到赞赏。提前致谢。

更新:仅在调试器中跟踪 ebp 和 esp:看起来当程序退出最后一个阶乘调用时,esp 是 ebp 的 +12,所以它在每次调用时加上 +4阶乘。结果,当程序点击 pop ebp 时,ebp 指向 r 而不是它应该指向的位置。有关如何解决此问题的任何建议?

【问题讨论】:

    标签: assembly recursion masm


    【解决方案1】:

    您需要删除在对factorial 的三个顶级调用之后出现的三个pop ebx 指令。由于factorial 已经将其参数从堆栈中弹出(通过使用ret 4),因此尝试通过执行pop ebx 再次删除参数会弄乱堆栈指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-02
      • 2014-06-24
      • 2014-11-18
      • 2013-11-22
      • 1970-01-01
      • 1970-01-01
      • 2019-07-24
      • 2013-10-07
      相关资源
      最近更新 更多