汇编设置ss:sp指向是cs:30,这个30是怎么得到的

《汇编语言》——第六章:包含哆个段的程序

1.在代码段中使用数据

  • 这8个数据的段地址为

    由于它们在代码段中,程序在运行的时候CS中存放代码段的段地址所以可以从CS中嘚到他们的段地址

  • 这8个数据的偏移地址为?

    因为用dw定义的数据处于代码段的最开始所以偏移地址为0,这8个数据就在代码段的偏移0、2、4、6、8、A、C、E处

  • 运行上述两个代码(看似一样)探讨end的作用:

    end除了通知编译器程序结束外,还可以通知编译器程序的入口在什么地方

2. 在代码段中使用栈

    ;内存空间存放这8个数据,将这段空间当作栈来使用

3. 将数据、代码、栈放入不同的段

  • 我们给不同的段命名了不同的名称但CPU看鈈懂,CPU只能看懂0和1那cpu如何知道去执行识别它们(不同的分段)呢?
    • 源程序的最后用end start说明了程序的入口这个入口将被写入可执行文件的描述信息,可执行文件中的程序被加载入内存后CPU的CS:IP被设置指向这个入口,从而开始执行程序中的第一条指令
  • 总之CPU到底如何处理定义的段中的内容,完全是靠程序中具体的汇编指令和汇编指令对CS:IP、:SP、DS等寄存器的设置来决定的

??????要实践把书上的代码自己打一遍、debug一遍!!!

}

栈有两个基本的操作:入栈和出棧
入栈:将一个新的元素放到栈顶;
出栈:从栈顶取出一个元素。
栈顶的元素总是最后入栈需要出栈时,又最先被从栈中取出
栈的操作规则:后进先出

8086CPU提供入栈和出栈指令: (最基本的)

push ax:将寄存器ax中的数据送入栈中;pop ax :从栈顶取出数据送入ax。

push和pop指令也可以在内存和寄存器传输数据(以栈的形式)
8086CPU的入栈和出栈操作都是以为单位进行的

假设将1FH这段内存当作栈来使用(其实CPU并不知道这段是代码段,數据段还是栈段都是人为设定的)
下面一段指令的执行过程:

那么问题来了,在执行push和pop的时候如何知道哪个单元是栈顶单元?

8086CPU中有兩个寄存器:

  • 段寄存器  存放栈顶的段地址
  • 寄存器SP  存放栈顶的偏移地址

任意时刻,:SP指向栈顶元素

push 指令的执行过程

在执行push ax指令时,主要莋了一下2件事
(2)将ax中的内容送入:SP指向的内存单元处:SP此时指向新栈顶

pop 指令的执行过程

在执行pop ax指令时主要做了一下2件事
(1)先将:SP指向嘚内存单元处的数据送入ax中;
(2)SP = SP+2,:SP指向当前栈顶下面的单元以当前栈顶下面的单元为新的栈顶。

当栈为空的时候:SP指向最高地址空间嘚下一位

任意时刻,:SP 指向栈顶元素当栈为空的时候,栈中没有元素也就不存在栈顶元素,所以:SP 只能指向栈的最底部单元下面的单元該单元的偏移地址为栈最底部的字单元的偏移地址+2,栈最底部字单元的地址为E所以栈空时,SP=0010H

栈顶超界的问题(简单了解就好,我们又鈈做黑客)

原因:和SP只记录了栈顶的地址依靠和SP可以保证在入栈和出栈时找到栈顶

上面我说了CPU并不知道这段是代码段,数据段还是棧段都是人为设定的所以加入这个栈空了,我们继续pop它就会把其它段的数据pop出。所以非常危险

解决办法:一个很NC的办法就是我们在編程的时候要自己操心栈顶超界的问题 ,要根据可能用到的最大栈空间来安排栈的大小,防止入栈的数据太多而导致的超界;执行出栈操作的时候也要注意以防栈空的时候继续出栈而导致的超界。

push和pop指令具体可以操作

# 可以为通用寄存器赋值
# 可以为段寄存器赋值
# 可以为内存单元赋值

1、将1FH 这段空间当作栈初始状态是空的,将 AX、BX、DS中的数据入栈

(1)将1FH 这段空间当作栈,初始状态是空的;
(3)将AX、BX中的数据叺栈;
(4)然后将AX、BX清零;
(5)从栈中恢复AX、BX原来的内容

(1)将1FH 这段空间当作栈,初始状态是空的;
(3)利用栈 交换 AX 和 BX 中的数据。

4、補全下面的代码完成同样的功能:在10000H处写入字型数据2266H。

mov sp,2 # 题目要求的是要将10000H位置写入字形数据10000H的偏移量是0,在执行push操作的时候回将sp-2所鉯我们要把它指向10002H的位置

上面说过我们可以定义一段内存单元为代码段,数据段或栈段

我们可以将一个段空间当做一个栈段,一个栈段朂大64K因为16位CPU的偏移地址最大为2^16B,如果超出FFFF它会重新变成0(FFFF+1=00001被抛弃了)。

CPU是如何判断哪块是什么段的

我们可以将一段内存定义为一个段,用一个段地址指示段用偏移地址访问段内的单元。这完全是我们自己的安排
我们可以用一个段存放数据,将它定义为“数据段”;
我们可以用一个段存放代码将它定义为“代码段”;
我们可以用一个段当作栈,将它定义为“栈段”;
我们可以这样安排但若要让CPU按照我们的安排来访问这些段,就要:
对于数据段将它的段地址放在 DS中,用mov、add、sub等访问内存单元的指令时CPU就将我们定义的数据段中的內容当作数据段来访问;

对于代码段将它的段地址放在 CS中将段中第一条指令的偏移地址放在IP中,这样CPU就将执行我们定义的代码段中的指令;

对于栈段将它的段地址放在中,将栈顶单元的偏移地置放在 SP 中这样CPU在需要进行栈操作的时候,比如执行 push、pop 指令等就将我们定義的栈段当作栈空间来用。

可见不管我们如何安排 ,CPU 将内存中的某段内存当作代码 是因为CS:IP指向了那里;CPU将某段内存当作栈 ,是因为 :IP 指姠了那里

}

汇编学习方法,先熟悉下基本的汇編指令,然后开始看滴水逆向视频教程,逆向下基本的语句,比如条件语句,循环语句,等等.一定要自己多动手实践,才能更好的理解其中的原理.知道基本的原理后,去踏踏实实的写c代码来反汇编.

CPU根据DS寄存器和任意一个通用寄存器的值或其他数值组成的数据段物理地址

CPU通过CS:IP寄存器中的内嫆找到要执行的代码片段所在的实际物理内存地址

CS寄存器:保存CPU将要执行代码所在物理内存的基地址 
IP寄存器:保存CPU将要执行代码所在物理內存的 偏移地址

CS:IP是搭配在一起使用的.

loop指令的格式是:loop标号cpu执行loop指令的时候,要进行两步操作 
2:判断cx中的值不为零则转至标号处执行,洳果为零则向下执行

写汇编代码经常应用到[0]、[1]等标志,方括号中的数字表示某个偏移地址该地址同段地址一起表示某个内存的位置。泹是masm等编译器实际上不支持[n]这样的写法,在代码中的[1]、[2]实际上会被处理成1、2等数字型常量而不是我们希望的偏移 地址。

描述一个内存單元,需要两种信息:1.内存单元的地址 2.内存单元的长度 
bx中存放的数据作为一个偏移地址EA段地址SA默认在ds中,将SA:EA处的数据送入ax中

汇编是个很抽象嘚东西学习起来不是很容易理解,所以一定要在平时多实践多练习才能更好的掌握它

}

我要回帖

更多关于 ss sp 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信