不能从递归循环返回主PROC - Stack Overflow

问题描述 投票:1回答:2

我试图编程一个简单的循环,调用自己,并跟踪它的循环次数。 当我踏过它时,一旦 ECX 里面的点击率为0 recursive PROC,它跳到 RET 里面 L1 - 我以为0之后会回到 main PROC

我的理解是,当一个过程被调用时,它会将指令指针推到堆栈上,然后当 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中得到 "无源代码可用 "的页面。

loops assembly recursion masm irvine32
2个回答
0
投票

如果我打印出 eaxmain 紧接着 CALL recursive 我得到 5所以你的代码 是否 回归 main. 问题是,你的 main 缺少一个 ret. 也就是说,应该改成。

main PROC
    mov eax, 0
    mov ecx, constant
    CALL recursive
    ret
main ENDP

因为你的程序应该在这里结束 你也可以使用Win32函数 invoke ExitProcess,0 而不是 ret.


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
© www.soinside.com 2019 - 2024. All rights reserved.