汇编语言课堂总结3——内存访问
Posted lingana
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了汇编语言课堂总结3——内存访问相关的知识,希望对你有一定的参考价值。
内存中字的存储
8086CPU中,用16位寄存器存储一个字,而在前面的学习中了解到内存是以字节为单位划分的,所以一个字要用两个地址连续的内存单元来存放,这就提出了字数据的存取原则(小端法):高—高,低—低,即,字数据的低位字节存放在低地址内存单元;字数据的高位字节存放在高地址内存单元;取低地址内存单元地址作为字数据地址。
ex.
除此之外,还有一种存储方法叫做大端法,顾名思义,和小端法的存储方式正好相反。
DS和[address] and 字的传送
DS,数据段寄存器,通常用来存放要访问的数据的段地址,在mov, add, sub等汇编指令中,访问内存单元时,默认情况下,指的是数据段。也就是说,我们可以通过改变DS中的值来访问指定的内存单元,但是8086CPU不允许直接将数据传入DS寄存器:
所以需要通过一般寄存器来实现过渡,比如:
MOV BX, 1000H
MOV DS, BX ;DS<-1000H
MOV AL, [0]
前两条mov指令完成了两种传送:①将数据直接送入寄存器;②将一个寄存器中的内容送入另一个寄存器。
“[...]”表示一个内存单元,“[...]”中的数据0表示内存单元的偏移地址。所以这三条指令实现的功能就是将10000H ( 1000:0 ) 中的数据读到AL中。
所以字的传送就是使用MOV指令通过16位寄存器在CPU和内存之间进行数据的传送,其中要使用数据段寄存器DS来访问内存单元。
ex.
MOV、ADD、SUB指令
MOV、ADD、SUB指令都有两个操作对象,操作对象可以是常数、寄存器、段寄存器和内存单元,但并不是任意两两组合都可以使用。
mov指令:1、两个操作数长度要一致。
2、常数(立即数)不能作为第1个操作数(目的操作数);作第2个操作数(源操作数)时,如果最高位是十六进制的a~f或A~F,前面要加零。
3、两个内存单元之间不能直接传送数据。
4、不能使用mov指令修改CS和IP的值。
5、两个段寄存器之间不能直接传送;不能把常数送到段寄存器。
add指令:1、操作数不能同时是内存单元。
2、操作数不能是段寄存器。
3、操作数是内存单元时,指令中只给出「偏移地址」。默认,「段地址」在ds中。
sub指令:1、两个内存单元不能直接使用sub指令相减。
2、操作数不能是段寄存器。
3、操作数是内存单元时,指令中只给出「偏移地址」。默认,「段地址」在ds中。
栈
栈是一个逻辑上的概念,可以将一段内存空间当作栈来使用。栈有“后进先出”的特性。8086CPU中栈以字为存取单位。
栈顶是最后入栈的字数据所对应的地址单元;栈底是固定的一端,栈区最高地址单元的前一个单元。8086CPU中有两个寄存器,SS(栈段段寄存器)和SP(栈指针寄存器),栈顶的段地址存放在SS中,偏移地址存放在SP中,任意时刻,SS:SP指向栈顶元素。
栈有两种操作:入栈push和出栈pop。
push:第1步,栈顶上移两个单元,即:栈顶-2 → 栈顶;第2步,存入数据。
pop:第1步,取出字数据5020H → AX;第2步,栈顶下移两个单元,即:栈顶+2 → 栈顶。(栈为空时,栈顶指向栈底+2)
push、pop指令形式:
注意:1、在push 内存单元和pop 内存单元中,指令中只需给出「偏移地址」。默认,段地址在DS中。
2、对8086CPU而言,push和pop的操作:入栈和出栈均以字为单元;操作对象不能是常数;pop 段寄存器中,段寄存器不能是CS和SS。
3、利用栈「后入先出」特性,使用push和pop指令可以完成一些特殊处理。
栈顶越界问题
当以下两种情形出现时会发生栈顶越界问题:
·当栈满的时候,再使用push指令入栈
·当栈空的时候,再使用pop指令出栈
因为每次入栈或出栈改变的都是SP中的值,但是SP的范围只能在0000~FFFFH之间,也就是说一个栈空间最大只能有64kb,并且8086CPU不会自动考虑栈顶越界,所以容易发生越界的情况。
越界情况发生后,也许不会有很大的影响,但也可能会访问到用户权限之外的内存,如果随意操作,可能会导致电脑出现故障;或者是在SP为FFFF时继续执行了pop操作,这时可能会取到我们不需要的垃圾数据。
疑问
在检测点3.1中有如下三条语句:
mov ax, 1
mov ds, ax
mov ax, [0000]
为什么执行完这三条语句后,AX中的值是0000:0010中的值,而不是0001:0000中的值呢?(有没有哪位大佬可以解答一下我的疑惑哇)
以上是关于汇编语言课堂总结3——内存访问的主要内容,如果未能解决你的问题,请参考以下文章