我应该写一个形状为
的c ++程序答案 0 :(得分:2)
正如杰斯特所指出的,这是一项愚蠢的任务,但如果你理解堆栈的话,你应该能够以任何方式解决它。
您当前的代码确实:
; For example let's say sp = 54 (address 54 in memory)
push ax ; store argument n, sp = 52
call suma ; do the call
; inside suma under the argument there are pushed also
; return address by CALL, sp =50
; and old bp by PUSH bp, sp = 48
; then [sp+4] points to argument n (48+4 = 52)
; stack is restored by the function ("ret 2"), sp = 54
现在,如果要将结果放在堆栈上,则必须从调用者的角度保留堆栈空间,因为在suma
返回后,sp
将恢复为&#34 ; 54"在我的示例中,从suma
调用低sp
地址写入堆栈的任何内容都可能已被覆盖(例如,如果在ret 2
和下一条指令之间发生中断,则中断执行使用地址54下面的堆栈内存,覆盖它)。在地址54+处写入内存的任何内容都可以在调用者中存活,但会破坏调用者在那里存储的值。
ax
中返回结果,因为它在以错误的方式进行递归的同时会覆盖它本身,并累积结果存储在地址sum
的内存中,未由suma
初始化,因此它只能运行一次。有可能以这种方式编写它,递归将返回正确的总和,即使是多次调用(首先将总和归零,然后调用F(n-1)并添加" n" as需要得到那个F(n-1))。
因此要么决定返回值而不是参数n,那么你必须:
suma
内将结果存储到[ebp+4]
内存ret
(不从堆栈中释放参数)call suma
到处pop ax
后从堆栈中选择结果或者在参数上方保留堆栈空间,例如:
sub sp,2 ; make space for result in stack
; you can also use another bogus "push ax", not caring about value, just adjusting sp
push ax ; push argument n
call suma
pop ax ; read result + restore stack
然后在suma
内,您必须将结果存储到[bp+6]
,ret 2
保持原样,只释放参数。
无论哪种方式,堆栈空间必须由调用者保留,因为任何未保留的堆栈空间(低于当前值sp
)都可能被中断处理程序随时覆盖(在x86 16b实模式下)。