【文档说明】汇编语言讲稿03课件.ppt,共(70)页,247.634 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44796.html
以下为本文档部分文字说明:
汇编语言讲稿03第3章寄存器(内存访问)3.1内存中字的存储3.2DS和[address]3.3字的传送3.4mov、add、sub指令3.5数据段3.6栈3.7CPU提供的栈机制3.8栈顶超界的问题3.9push、po
p指令3.10栈段引言在第2章中,我们主要从CPU如何执行指令的角度讲解了8086CPU的逻辑结构、形成物理地址的方法、相关的寄存器以及一些指令。这一章中,我们从访问内存的角度继续学习几个寄存器。在0
地址处开始存放20000(4E20H)0号单元是低地址单元,1号单元是高地址单元。3.1内存中字的存储3.1内存中字的存储问题:(1)0地址单元中存放的字节型数据是多少?(2)0地址字单元中存放的字型数据是多少?
(3)2地址字单元中存放的字节型数据是多少?3.1内存中字的存储问题:(4)2地址单元中存放的字型数据是多少?(5)1地址字单元中存放的字型数据是多少?结论3.1内存中字的存储结论:任何两个地址连续的内存单元,N
号单元和N+1号单元,可以将它们看成两个内存单元,也可以看成一个地址为N的字单元中的高位字节单元和低位字节单元。3.2DS和[address]CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址;在8086PC中,内存地址由段地址和偏移地址组成。8086CPU中有一个DS寄存
器,通常用来存放要访问的数据的段地址。例如3.2DS和[address]例如:我们要读取10000H单元的内容,送入寄存器al中。3.2DS和[address]已知的mov指令可完成的两种传送功能:(1)将数据直接送入寄存器;(2
)将一个寄存器中的内容送入另一个寄存器中。mov指令还可以将一个内存单元中的内容送入一个寄存器。3.2DS和[address]从哪个内存单元送到哪个寄存器中呢?mov指令的格式:mov寄存器名,[偏移地址]3.2DS和[addr
ess]执行指令时,8086CPU自动取DS中的数据为内存单元的段地址。如何把1000H送入ds?传送指令movds,1000H?8086CPU不支持将数据直接送入段寄存器的操作,ds是一个段寄存器。movds,1000H是非法的。数据一般的寄存器段寄
存器正确:movbx,1000Hmovds,bx错误3.2DS和[address]下面三条指令将10000H(1000:0)中的数据读到al中。movbx,1000Hmovds,bxmoval,[0]3.2DS和[address]
问题:写几条指令,将al中的数据送入内存单元10000H?(思考后分析)分析问题本质:怎样将数据从寄存器送入内存单元?结论:movbx,1000Hmovds,bxmov[0],al3.3字的传送因为8086CPU是16位结构,有16根数据线,所以,可以
一次性传送16位的数据,也就是一次性传送一个字。问题3.3:内存中的情况如右图,写出下面指令执行后寄存器ax,bx,cx中的值。3.3字的传送3.4mov、add、sub指令已学mov指令的几种形式:mov寄存器,数据mov寄存器,寄存器mov寄存器,内
存单元mov内存单元,寄存器mov段寄存器,寄存器add和sub指令同mov一样,都有两个操作对象。它们可以对段寄存器进行操作吗?3.4mov、add、sub指令3.5数据段前面讲过,对于8086PC机,我们可以根据需要将一组内存单元
定义为一个段。我们可以将一组长度为N(N≤64K)、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段。比如我们用123B0H~123B9H这段空间来存放数据:段地址:123BH长度:10字节3.5数据段如何访问数据段中的数据呢?将一段内存当
作数据段,是我们在编程时的一种安排,我们可以在具体操作的时候,用ds存放数据段的段地址,再根据需要,用相关指令访问数据段中的具体单元。示例3.5数据段我们将123B0H~123BAH的内存单元定义为数据段,我们现在要累加这个数据段中的前3个单元中的数据,代码如下:3.5数据段
问题3.5写几条指令,累加数据段中的前3个字型数据。思考后看分析。问题3.5分析注意:一个字型数据占两个单元,所以偏移地址是0、2、4。3.1节~3.5节小结(1)字在内存中存储时,要用两个地址连续的内存单元来存放,字的低位字节存放在低地址单元中,
高位字节存放再高地址单元中。(2)用mov指令要访问内存单元,可以在mov指令中只给出单元的偏移地址,此时,段地址默认在DS寄存器中。(3)[address]表示一个偏移地址为address的内存单元。3.1节~3
.5节小结(续)(4)在内存和寄存器之间传送字型数据时,高地址单元和高8位寄存器、低地址单元和低8位寄存器相对应。(5)mov、add、sub是具有两个操作对象的指令。jmp是具有一个操作对象的指令。3.6栈我们研究栈的角度:栈是一种具有特殊的访问
方式的存储空间。它的特殊性就在于,最后进入这个空间的数据,最先出去。可以用一个盒子和3本书来描述栈的操作方式3.6栈栈有两个基本的操作:入栈和出栈。入栈:将一个新的元素放到栈顶;出栈:从栈顶取出一个元素。栈顶的元素总是最后入栈,需要出栈时,又最先被
从栈中取出。栈的操作规则:LIFO(LastInFirstOut,后进先出)3.7CPU提供的栈机制8086CPU提供相关的指令来以栈的方式访问内存空间。这意味着,我们在基于8086CPU编程的时候,可以将一段内存当作栈来使
用。3.7CPU提供的栈机制8086CPU提供入栈和出栈指令:(最基本的)PUSH(入栈)POP(出栈)pushax:将寄存器ax中的数据送入栈中;popax:从栈顶取出数据送入ax。8086CPU的入栈和出栈操作都是
以字为单位进行的。3.6栈下面举例说明,我们可以将10000H~1000FH这段内存当作栈来使用。下面一段指令的执行过程:movax,0123Hpushaxmovbx,2266Hpushbxmovcx,1122Hpushcxpopaxpopbxpopcx3.6
栈指令序列的执行过程演示注意:字型数据用两个单元存放,高地址单元放高8位,低地址单元放低8位。是否有疑惑?两个疑问两个疑问1、CPU如何知道一段内存空间被当作栈使用?2、执行push和pop的时候,如何知道哪个单元是栈顶单元?分析结论:任意时刻,SS:SP指向栈顶元素。对于两个疑问的
分析回想:CPU如何指导当前要执行的指令所在的位置?寄存器CS和IP中存放着当前指令的段地址和偏移地址。8086CPU中,有两个寄存器:段寄存器SS存放栈顶的段地址寄存器SP存放栈顶的偏移地址任意时刻,SS:SP指向栈顶元素。push指令的执行过程pushax(1)SP=SP–2;(2)
将ax中的内容送入SS:SP指向的内存单元处,SS:SP此时指向新栈顶。图示push指令的执行过程3.6栈问题3.6:如果我们将10000H~1000FH这段空间当作栈,初始状态栈是空的,此时,SS=1000H,SP=?思考后看分析。问题3.6分析SP=0010Hpop
指令的执行过程popax(1)将SS:SP指向的内存单元处的数据送入ax中;(2)SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。图示pop指令的执行过程注意pop指令的执行过程注意:出栈后,SS:SP指向新的栈顶1000EH,pop操作前的栈顶元素
,1000CH处的2266H依然存在,但是,它已不在栈中。当再次执行push等入栈指令后,SS:SP移至1000CH,并在里面写入新的数据,它将被覆盖。3.8栈顶超界的问题SS和SP只记录了栈顶的地址,依靠SS和SP可以保证在入栈
和出栈时找到栈顶。可是,如何能够保证在入栈、出栈时,栈顶不会超出栈空间?3.8栈顶超界的问题栈顶超界是危险的:因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放了具有其他用途的数据、代码等,这些数据、代码可能是我们自己的程序中的,也可能是别的程序中的。3.8栈顶超
界的问题但是由于我们在入栈出栈时的不小心,而将这些数据、代码意外地改写,将会引发一连串的错误。我们当然希望CPU可以帮我们解决这个问题,3.8栈顶超界的问题比如说在CPU中有记录栈顶上限和下限的寄存器,我们可以通过填写这些寄存器来指定栈空间的范围,然后,CPU在执行p
ush指令的时候靠检测栈顶上限寄存器,在执行pop指令的时候靠检测栈顶下限寄存器保证不会超界。实际情况:8086CPU中并没有这样的寄存器。8086CPU不保证对栈的操作不会超界。这就是说,8086CPU只知道栈顶在何处(由SS:SP指示),而不知道读者安排的栈空间有多大
。3.8栈顶超界的问题结论:我们在编程的时候要自己操心栈顶超界的问题,要根据可能用到的最大栈空间,来安排栈的大小,防止入栈的数据太多而导致的超界;执行出栈操作的时候也要注意,以防栈空的时候继续出栈而导致的超界。3.9push、pop指令push和pop指令是可以在寄存器和内存
之间传送数据的。push和pop指令的格式栈与内存栈空间当然也是内存空间的一部分,它只是一段可以以一种特殊的方式进行访问的内存空间。3.9push、pop指令push和pop指令的格式(1)push寄存器:将一个寄存器中的数据入栈pop寄存器:出栈,用一个寄存器接收出栈的
数据例如:pushaxpopbx3.9push、pop指令push和pop指令的格式(2)push段寄存器:将一个段寄存器中的数据入栈pop段寄存器:出栈,用一个段寄存器接收出栈的数据例如:pushdspopes3
.9push、pop指令push和pop指令的格式(3)push内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位)pop内存单元:出栈,用一个内存字单元接收出栈的数据例如:push[0
]pop[2]3.9push、pop指令问题3.7编程:将10000H~1000FH这段空间当作栈,初始状态是空的,将AX、BX、DS中的数据入栈。思考后看分析。问题3.7分析3.9push、pop指令问题3.8编
程:(1)将10000H~1000FH这段空间当作栈,初始状态是空的;(2)设置AX=001AH,BX=001BH;(3)将AX、BX中的数据入栈;(4)然后将AX、BX清零;(5)从栈中恢复AX、BX原来的内容。思考后看
分析。问题3.8分析结论问题3.8分析从上面的程序我们看到,用栈来暂存以后需要恢复的寄存器中的内容时,出栈的顺序要和入栈的顺序相反,因为最后入栈的寄存器的内容在栈顶,所以在恢复时,要最先出栈。3.9push、pop指令问题3
.9编程:(1)将10000H~1000FH这段空间当作栈,初始状态是空的;(2)设置AX=002AH,BX=002BH;(3)利用栈,交换AX和BX中的数据。思考后看分析。问题3.9分析3.9push、p
op指令问题3.10我们如果要在10000H处写入字型数据2266H,可以用以下的代码完成:movax,1000Hmovds,axmov,ax,2266Hmov[0],ax补全下面的代码3.9push、pop指
令补全下面的代码,完成同样的功能:在10000H处写入字型数据2266H。______________________________movax,2266Hpushax要求:不能使用“mov内存单元,寄存器”这类指令思考后看分析。问题3.10分析我们看需补全
代码的最后两条指令,将ax中的2266H压入栈中,也就是说,最终应由pushax将2266H写入10000H处。问题的关键就在于:如何使pushax访问的内存单元是10000H。Push指令是入栈指
令。(注意执行过程)完成程序问题3.10分析(续)完成的程序:movax,1000Hmovss,axmovsp,2movax,2266Hpushax结论3.10栈段将一段内存当作栈段,仅仅是我们在编程时的一种安排,CPU并不会由于这种
安排,就在执行push、pop等栈操作指令时就自动地将我们定义的栈段当作栈空间来访问。如何使的如push、pop等栈操作指令访问我们定义的栈段呢?将SS:SP指向我们定义的栈段。3.10栈段比如我们将10010H~1001FH这段长度为16字节的内存空间当作
栈来用,以栈的方式进行访问。这段空间就可以成为栈段,段地址为1000H,大小为16字节。3.10栈段问题3.11如果我们将10000H~1FFFFH这段空间当作栈段,初始状态是空的,此时,SS=1000H,SP=?思
考后看分析。问题3.11分析我们将10000H~1FFFFH这段空间当作栈段,SS=1000H,栈空间大小为64KB,栈最底部的字单元地址为1000:FFFE。任意时刻,SS:SP指向栈顶,当栈中只有一个
元素的时候,SS=1000H,SP=FFFEH。问题3.11分析栈为空,就相当于栈中唯一的元素出栈,出栈后,SP=SP+2。SP原来为FFFEH,加2后SP=0,所以,当栈为空的时候,SS=1000H,SP=0。