第十八课_几条跟堆栈扯上关系的汇编指令

前言

堆栈算是非常重要的结构了,今晚讲讲它是怎么设计的,最后讲几个跟堆栈相关的汇编指令。

初识堆栈结构

之前学过那些通用寄存器,读取方便,而且快速,但是有一个问题:就是寄存器有大小限制,数据量大的时候,寄存器就不够用了。为了实现存取大量的数据,并且能快速读取数据,前人发明了堆栈的结构。

堆栈的结构是这样的,分配一段连续的内存,定义两个变量BASE(栈底)、TOP(栈顶)。

BASE(栈底)里面保存一个地址,记录该连续内存(堆栈)的起始地址。

TOP(栈顶)里面保存一个地址,记录该连续内存(堆栈)的结束地址。

这两个变量保存栈底、栈顶的内存地址,这两个变量的值(内存地址)分别保存通用寄存器EBP和ESP中。

说那个多,来点实在的,看看OD中的堆栈长什么样的吧。

可以看到堆栈就是一块连续的内存,只不过这段连续的内存的开始地址保存在EBP寄存器中,结束地址保存在ESP中。这么看,其实堆栈也没想的那么复杂。大家可能也注意到OD的堆栈中栈顶的地址的背景色是深黑色的。

向栈中放入一个数(假设4个字节)时,TOP(栈顶)的值减4。可以看下面的示意图。

向栈中放入一个数的过程,叫入栈。在windows系统中,栈是向低位扩展的,所以入栈的时候地址是减去一个数。

在OD中执行了一条入栈的命令,可以看到这样的结果。

从栈中取出一个数(假设4个节字)时,BASE(栈底)的值加4。可以看下面的示意图。

从栈中取出一个数的过程,叫出栈可以看到出栈时,只是把栈顶的地址改变,并没有去删除原来栈顶的值。

在OD中执行一条出栈的命令,可以看到原来栈顶的值还是存在内存中的。

如果要读取栈中间的某个值,可以通过栈顶或栈底加上一个偏移量的方式去读取。

 

可以看到用这种方式读取内存的数据非常快,直接加偏移量就能读取内存中的值。

详细说说入栈、出栈

入栈时,在OD中可以发现,ESP中的值减了4,栈顶上移,并且把值放入到栈顶中。我们可以用已经学过的指令实现这一过程。

mov dword ptr ds:[ESP-4],0xA

sub ESP,0x4

当然还有其他的方式实现。

其实汇编中还有一个更好用的指令实现入栈的过程:push指令。

push指令

格式:push r32/r16/m16/m32/imm8/imm16/imm32

例子:push eax :把EAX寄存器中的值压入栈中。

执行前栈的情况

执行后栈的变化情况

出栈时,也可以用已经学过的指令来实现。

mov EAX, dword ptr ds:[ESP]

add ESP,0x4

当然汇编中也有一条命令实现出栈的过程:pop指令

pop指令

格式:pop r16/r32/m16/32   注意pop后面不能是立即数,因为pop后面要有一个容器接收从栈中取出的数。

例子:pop ecx :把栈顶的值取出放入到ECX寄存器中。

执行前栈的情况

执行后栈的情况

这篇文章就写这么多吧,本来还想写lea、callret等指令的,留到下次吧。

 

 

写于2020.6.12 22:55

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值