无法从递归循环返回到主PROC - Stack Overflow

时间:2015-03-31 03:00:36

标签: loops assembly recursion masm irvine32

我正在尝试编写一个调用自身的简单循环,并跟踪它循环的次数。当我单步执行时,ECXrecursive PROC内点击0后,它会跳转到RET内的L1 - 我认为在0之后会返回main PROC < / p>

我的理解是,当一个过程被调用时,它会将指令指针推到堆栈上,然后当调用RET时,它会将其弹出并返回到该点。

; Calls a recursive procedure
;

INCLUDE Irvine32.inc

.data

constant DWORD 5
count DWORD ?

.code
main PROC
    mov eax, 0
    mov ecx, constant
    CALL recursive
main ENDP

recursive PROC
    add eax, 1
    loop L1
    ret
    L1:
        CALL recursive
        ret
recursive ENDP

END main

当我从RET中取出L1时,我会在Visual S 2013中找到“无可用源代码”页面。

2 个答案:

答案 0 :(得分:0)

如果我在eax main之后立即在CALL recursive打印5的值,那么我的代码返回{ {1}}。问题是您的main缺少main。也就是说,它应该改为:

ret

由于这是你的程序应该结束的地方,你也可以使用Win32函数main PROC mov eax, 0 mov ecx, constant CALL recursive ret main ENDP 而不是invoke ExitProcess,0

答案 1 :(得分:0)

最初答案的问题是,在递归调用函数之后,返回地址已被递归函数压入堆栈而被掩埋。每次执行调用时,将包含过程的返回地址压入堆栈,并使ESP递减。如果我们不递归地继续递归调用函数,则堆栈将包含所有这些重复的地址,并且ESP指向最后一次调用。

您将需要从堆栈中弹出所有这些递归函数调用,以使ret指令有效。您可以使用调试器验证此行为:

.386
.model flat,stdcall
.stack 4096

includelib  Irvine32.lib
includelib  User32.lib
include     Irvine32.inc

.code
main PROC
    mov eax,0
    mov ecx,5               ; # calls to perform
    call    recurs
    call    WriteInt

    INVOKE ExitProcess,0

main ENDP

; input   - ecx, parameter for  # function calls to perform
; uses ebx as workspace to dump junk from the stack 
recurs  PROC 
    loop    L1
    mov     ecx,eax     ; we need to keep track of recursive call count. 
L2: pop     ebx
    loop    L2
    inc     eax         ; add 1 for the initial call to made to recurs     
    ret                 ; ret pops the address currently pointed to by
L1: inc     eax         ; by ESP into EIP.         
    call    recurs      
recurs  ENDP            

END main
相关问题