汇编 | 二、数据段、栈机制与栈段
汇编 | 二、数据段、栈机制与栈段
第二篇主要讲解汇编中规定的代码段与栈段,其中将讲解常见的栈机制
0x01 DS和[addres]所表示的数据段
在上一篇中讲了关于代码段的内容,那么这一篇就要先来介绍一下汇编是如何表示数据段的
我们使用CS:IP来表示代码段,一个这个段也就是一段物理地址,由段地址和偏移地址来记录,在代码段中,cs就是代码段的段寄存器,ip就是偏移地址,同理,在数据段中,我们也可以使用类似的方式来表示一个数据段,那么在这里使用的就是DS这个段寄存器,我们不能直接给段寄存器赋值,而要以 “mov 段寄存器,寄存器” 这样的方式来给ds一个值。
但是,表示数据段偏移地址的并不是什么特殊的寄存器,而是以 **[0000]**这样的形式来表示的,中括号里面的数值,就是偏移地址。
下面通过几幅图来给大家简单的介绍一下使用方法:
首先,看一下初始状态:
然后我们在debug中执行一下,先看一下debug中的各部分信息:
要执行的代码:
将操作的内存数据:
各个寄存器的当前状态:
接下来开始执行代码:
注意:这里使用 t 命令来执行代码,r 是查看寄存器, d是查看一段内存地址!
这里执行了 mov ax,1000 ,可以看到,执行后,AX的值变成了1000
这一步执行了 mov ds,ax ,然后ds中的值变成了1000
这一步执行了 mov ax,[0] ,将1000:0000位置的一个字单元写入到了ax中
这一步执行了 mov bx,[4] ,将1000:0004处的字单元写入到了bx中
这一步执行了 mov al,[1] ,这里是将1000:0001处的一个字节写入到了al这个寄存器中
顺便说一下,ax是一个16位寄存器,它有ah和al组成,ah和al分别代表,ax的高8位和低8位,所以这里只读取了一个字节的数据
这里执行了 mov [0],ax ,将ax中的值写入了1000:0000处
这里 mov [6],bh ,同理,将bh的值送入了1000:0006处
至此,代码执行结束!
数据段只是用于存放一些数据的,以便在代码执行的过程中更好的读取数据。
0x02 栈机制
相信学习编程的小伙伴一定都听说过栈这个数据结果,汇编中的栈机制和数据结构中的栈是一个概念,所有在这里将简单描述一下:
栈就像是一个筒装的羽毛球,如果你想拿走最底下的羽毛球,就必须先挨个把上面的羽毛球都拿出来,(由于羽毛球过于抽象,我还是用乒乓球代替吧)下面献上万能的图:
这里如果我们想要拿到球A就必须先吧上面的三个球拿出来,所以拿球的顺序应该是,D --> C --> B --> A
这样我们就可以得到球A了,我们如果先将球A放入空筒中,那么这个球也一定时最后一个被拿出来的。
从拿球放球的过程中我们可以看出来一个规律,先进后出,凡是先放进去的都是后面才能拿到的。
这个筒就好比一个栈,拿球就是出栈,放球就是入栈,这个就是所谓的栈机制。
0x03 栈段
栈段,又是一个段,那么一定就有段地址和偏移地址,接下来讲一下8086中栈的基本寄存器和运行过程。
首先,8086提供了SS和SP来让我们定义栈段,SS表示段地址,SP表示偏移地址。
同时还有入栈和出站的操作,入栈使用push指令,而出站使用pop指令。
这里的SS:SP所指向的内存单元将是这个栈的栈顶!
mov ax,1000
mov ss,ax
mov sp,10
先执行以上程序将ss和sp初始化。然后开始入栈操作
mov ax, ae09
push ax
执行时,先将ae09给ax,然后push ax时,首先sp-2,这样,sp就等于e,SS:SP也就指向了1000:e,然后再将ax的值送入ss:sp所指向的地址。然后再执行pop bx指令,先将ss:sp指向地址的内容写入到bx中,然后将sp+2,这样栈又恢复到了空的状态。
注意:栈段是从高地址到低地址的。另外,栈的操作只用于字单元!
这里要注意栈的操作可能会导致栈顶超界的问题,当我们不停的push时,sp会不停的-2,当ss:sp超出了我们所规定的栈段时,将可能造成数据覆盖的风险,cpu并没有提供检查机制,所以要注意!