关于汇编中Ret指令执行后ESP的指向问题

AkeyMaker 2015-10-29 04:07:14
附上源码
.386
.model flat,stdcall
.code
main proc USES ecx edx
push ebp
mov ebp,esp
mov eax,[ebp + 8]
pop ebp
ret 4

main endp
end main
以下是执行后的堆栈记录:
EBP ESP 指令 Remark
0018FA60 0018F814 程序执行前
0018FA60 0018F810 PUSH ECX

0018FA60 0018F80C PUSH EDX

0018FA60 0018F808 PUSH EBX

0018F808 0018F808 MOV
0018F808 0018F808 MOV
0018FA60 0018F80C POP EBP
0018FA60 0018F810 POP EDX
0018FA60 0018F814 POP ECX
0018FA60 0018F81C Ret 4

这里有个疑问Ret4执行后也就是ESP+4,地址应该是0018F818,为什么这里ESP指向了0018F81C,这不是ESP+8了么???
请帮忙理解下,感谢!
...全文
907 6 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
zara 2015-11-03
  • 打赏
  • 举报
回复
两次 ret 0 ?不明白究竟是怎么理解这个指令的,你看的什么书上怎么说明这个指令的啊?最权威的还是 intel 提供的开发手册的卷II 指令参考:
引用
Description
Transfers program control to a return address located on the top of the stack. The address is usually placed on the stack by a CALL instruction, and the return is made to the instruction that follows the CALL instruction.
The optional source operand specifies the number of stack bytes to be released after the return address is popped; the default is none. This operand can be used to release parameters from the stack that were passed to the called procedure and are no longer needed. It must be used when the CALL instruction used to switch to a new procedure uses a call gate with a non-zero word count to access the new procedure. Here, the source operand for the RET instruction must
specify the same number of bytes as is specified in the word count field of the call gate.

ret 就是 ret,出栈参数就是出栈参数,不可混淆的,毕竟平衡参数时,并没有影响到 IP,所以两次 ret 0 的想法是不对的。
AkeyMaker 2015-11-02
  • 打赏
  • 举报
回复
引用 2楼路客尘 的回复:
函数调用的过程如下: 0.入参n个字节 1.push当前的CS 2.push 当前的IP 3.被调用函数的段地址--》》CS 4.被调用函数的偏移offset==》》EIP 5.就是你贴出的第一部分了 下面谈返回操作,return 如果ret指令附加了可选的n作为参数,那么sp <- sp + n,用来释放入栈的函数参数,之后继续执行下一步。。。 ============= 按照0-5步骤,回退,就是返回的操作 zara大大的ret4+4,我不同意。 Intel的文档里写的是,ret n就是用来清理入栈的参数,n就是表明了入栈的字节数,4+4一说我不觉得是这样。
但是最后调试的结果却像是执行了两次ret 0
AkeyMaker 2015-11-02
  • 打赏
  • 举报
回复
引用 1楼zara 的回复:
你不了解 ret 4 的具体操作吧,它是在 ret 返回后在将 esp 加上 4 以略过调用子程时压栈的参数区,达到堆栈平衡;一个 ret 是 +4,再 应 ret 4 +4 总的就是 +8 了。
感谢zara大大。根据调试的结果是这样没错。但是书里和intel 手册没找到佐证。
  • 打赏
  • 举报
回复
ret n就是ret之后附加弹出n字节的参数,你自己理解吧。
路客尘 2015-10-30
  • 打赏
  • 举报
回复
函数调用的过程如下: 0.入参n个字节 1.push当前的CS 2.push 当前的IP 3.被调用函数的段地址--》》CS 4.被调用函数的偏移offset==》》EIP 5.就是你贴出的第一部分了 下面谈返回操作,return 如果ret指令附加了可选的n作为参数,那么sp <- sp + n,用来释放入栈的函数参数,之后继续执行下一步。。。 ============= 按照0-5步骤,回退,就是返回的操作 zara大大的ret4+4,我不同意。 Intel的文档里写的是,ret n就是用来清理入栈的参数,n就是表明了入栈的字节数,4+4一说我不觉得是这样。
zara 2015-10-30
  • 打赏
  • 举报
回复
你不了解 ret 4 的具体操作吧,它是在 ret 返回后在将 esp 加上 4 以略过调用子程时压栈的参数区,达到堆栈平衡;一个 ret 是 +4,再 应 ret 4 +4 总的就是 +8 了。

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧