汇编原理笔记2~3章

文章详细介绍了8086CPU的结构,包括通用寄存器、字存储、汇编指令如mov和sub,以及物理地址和段的概念。段寄存器如CS和IP在CPU指令执行中的作用也被阐述,同时提到了栈的操作和越界问题。
摘要由CSDN通过智能技术生成

第二章

cpu:运算器,控制器,寄存器等组成他们靠内部总线相连

区别:内部总线实现cpu内部各器件的联系

​ 外部总线实现cpu和主板上其他器件的联系

8086CPU有十四个寄存器:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,CC,DC,EC,PSW.

2.1通用寄存器

8086CPU所有的寄存器都是16位的,可以存放两个字节。

AX,BX,CX,DX通用寄存器用来存放一般数据
在这里插入图片描述
数据18
二进制表示10010在这里插入图片描述
一个16位二进制数能存储最大的数值是2的16次方减1(因为从0开始)
8086上一代CPU寄存器是八位的
为保兼容性这四个通用寄存器可以分为两个独立的寄存器(如:AX可分为AH和AL)(高和低)
请添加图片描述
八位寄存器存储最大数值2的八次方减1

2.2字在寄存器中的存储

一个字=两个字节
刚好每四个二进制可以转换为一个十六进制数
故常用这两种
十六进制后面加上H二进制后面加上B
(每两位二进制对应一个八进制)

2.3几条汇编指令

汇编指令不区分大小写!!
请添加图片描述
赋值方法是从后往前赋值
注意16进制加减(满十六进一)
只能存16位(8226+8226=1044c)寄存器会记为044c
al和ah是独立的当al为c5H时add al,85H计算结果为0158但显示58
cpu不会真的丢弃进制位,后面会讨论!

2.4物理地址

CPU访问单元时要给出内存单元的地址。所有的内存单元 构成的存储空间是一个一维的线性空间。
我们将这个唯一的地址称为物理地址。

2.5 16位结构的CPU

十六位结构描述了CPU的以下几个方面特征
1.运算器一次最多可以处理16位的数据。
2.寄存器的最大宽度位16位.
3.寄存器和运算器之间的通路是16位的。

2.6 8086CPU给出物理地址的方法

8086有20位地址总线,可传送20地址,寻址能力为1MB.
8086内部位16位结构,它只能传送16位的地址,表现出的寻址能力却只有64K。
8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址。
在这里插入图片描述
地址加法器工作原理:物理地址=段地址×16+偏移地址
在这里插入图片描述
“段地址×16”有一个更常用的说法就是数据向左移四位。(二进制位)
在这里插入图片描述
经推断:一个X进制形式左移1位,相当于乘以X。
在这里插入图片描述

第一张纸条乘10加第二张纸条等想要传递的信息。

2.8 段的概念

内存并没有分段,段的划分来自于CPU,由于8086CPU用“(段地址×16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使我们可以用分段的方式来管理内存。(段是方便人来区分的,对CPU而言段是一体的(可以想一下物理中的磁感线))

以后,在编程时可以根据需要,将若干地址连续的内存看作一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。
注意:偏移地址为十六位,十六位地址的寻址能力为64K,所以一个段的长度最大为64K.
思考:(1) 观察下面的图片在这里插入图片描述 发现:一个物理地址可以有多种方式通往(条条大路通罗马)
结论:CPU可以用不同的段地址和偏移地址形成同一个物理地址。
(2)如果给定一个段地址,仅通过变化偏移地址及进行寻址,最多可以定位多少个内存单元?
结论:偏移地址位16位,变化范围位0~FFFFH,仅用偏移地址来寻址可寻64K个内存单元。
比如:给定段地址1000H,用偏移地址寻址,CPU的寻址范围位:10000H~1FFFF。

2.9段寄存器

段寄存器就是提供段地址的。
8086CPU有4个段寄存器:
CS:代码段地址寄存器
DS:数据段地址寄存器
SS:堆栈段地址寄存器
ES:附加段地址寄存器(如果前三个放不下时放这个里)
当8086CPU要访问内存时,有这4个段寄存器提供内存单原的段地址

2.10CS和IP

CS和IP是CPU中最关键的寄存器,它们指示了CPU当前要读取指令的地址。
CS为代码寄存器
IP为指令指针寄存器。
请添加图片描述
8086CPU工作过程的简要描述
(1)从CS:IP指向内存单元读取指令,读取的指令进入指令缓冲区;
(2)IP=IP+所读取指令的长度,从而指向下一条指令:
(3)执行指令。转到步骤(1),重复这个过程。
在8086CPU加电或复位后(即CPU开始工作时)CS和IP被设置为CS=FFFFH,IP=0000H。
即在8086PC机刚启动时,CPU从内存FFFF0H单元中读取指令执行。
FFFF0H单元中的指令是8086PC机开机后的执行的第一条指令。

2.11修改CS,IP的指令

在CPU中,程序员能够用指令读写的部件只有寄存器,程序员可以通过改变寄存器中的内容实现对CPU的控制。
MOV指令可以改变8086CPU大部分寄存器的值,被称为传送指令。
MOV 不能用于设置CS,IP的值,8086CPU没有提供这样的功能。
8086CPU为CS,IP提供了另外的指令来改变他们的值:转移指令
同时修改CS,IP的内容:
jmp段地址:偏移地址
jmp 2AE3:3
jmp 3:0B16
功能:用指令中给出的段地址修改CS,偏移地址修改IP。
仅修改IP的内容:
jmp某一合法寄存器
jmp ax(类似于 mov IP,ax)
jmp bx
功能:用寄存器中的值修改IP。

2.12代码段

对于8086PC机,在编辑时,可以根据需要,将一组内存单元定义为一个段。
可以将长度为N(N<=64KB)的一组代码,存在一组地址连续,起始地址为16的倍数的内存单元中,这段内存是用来存放代码的,从而定义了一个代码段。
例如:在这里插入图片描述

这段长度为10字节的指令,存在从123B0H~ 123B9H的一组内存单元中,我们就可以认为,123B0H~123B9H这段内存单元是用来存放代码的,是一个代码段,他的段地址为123BH,长度为10字节
(1字节=8位2进制数)
CPU只认被CS:IP指向的内存单元中的内容为指令。
所以要将CS:IP指向所定义的代码段中的第一条指令的首地址。

实验一

R命令查看,改变CPU寄存器的内容;
D命令查看内存中的内容;
E命令改变内存中的内容;
U命令将内存中的机器指令翻译成汇编指令。
T命令执行一条机器指令;
A命令以汇编指令的格式在内存中写入一条机器指令。

第三章

3.1内存中字的存储

任何两个地址连续的内存单元,N号单元和N+1号单元,可以将他们看成两个内存单元,也可以看成一个地址为N的字单元中的高位字节单元和低位字节单元。请添加图片描述

3.2DS和【adderss】

CPU要读取一个内存单元的时候,必须先给出这个内存单元的地址;
8086CPU中,有一个DS寄存器,通常用来存放要访问的数据的段地址。
例如:在这里插入图片描述
已知的mov指令可完成的两种传送功能:
(1)将数据直接送入寄存器。
(2)将一个寄存器中的内容送入另一个寄存器中。
除此之外,mov指令还可以将一个内存单元中的内容送入一个寄存器。
例:mov ax,[0]
其中[ ]中的0表示偏移地址
8086CPU不支持直接将数据送入段寄存器的操作,ds是一个段寄存器。(即mov ds,1000H非法)
正确的方式:数据->通用寄存器->段寄存器
如何将数据从寄存器送入内存单元?
mov [0],al

3.3字的传送

因为8086CPU是16位结构,有16根数据线,所以可以一次性传送16位数据,也就是一次性传送一个字。
比如:
在这里插入图片描述

3.4mov add sub指令

sub是减法
在这里插入图片描述

3.5 数据段

定义方法:将一组长度为N(N<=64KB),地址连续,起始地址为16的倍数的内存单元当作专门存储数据的内存空间。
例:我们用123B0H~123B9H这段空间来存放数据:
段地址:123BH
长度:10字节
访问方法:用ds存放数据段的段地址,再根据需要,用相关指令(如偏移地址)访问数据段中的具体单元。
注意一个字型数据占两个单元,所以偏移地址是0,2,4.(一个字是俩字节)

3.6 栈

栈是一个具有特殊的访问方式的存储空间。它的特殊性就在于,最后进入这个空间的数据最先出去。
例如:(一个盒子(下封底)和三本书)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
栈有两个基本操作:入栈和出栈。
入栈:将一个新的元素放到栈顶;
出栈:从栈顶取出一个元素。
栈顶的元素最后入栈,需要出栈时,又最先被从栈中取出。
栈的操作规则:LIFO
(Last In First Out,后进先出)

3.7CPU提供的栈的机制

现今的CPU都有栈的设计。
8086CPU提供入栈和出栈指令:(最基本的)
PUSH(入栈)
POP(出栈)
push ax:将寄存器ax中的数据送入栈中;
pop ax:从栈顶取出数据送入ax。
8086CPU的入栈和出栈操作都是以字(16位)为单位进行的。
CPU如何指导当前要执行的指令所在的位置?
答:寄存器CS和IP存放着当前指令的段地址和偏移地址。
8086CPU中,有两个寄存器:
段寄存器SS 存放栈顶的段地址
寄存器SP 存放栈顶的偏移地址
结论:任何时刻,SS:SP指向栈顶元素。
push指令的执行过程
push ax
(1)SP=SP-2;(底在下端,入栈是sp往上走是减)
(2)将ax中的内容送入SS:SP指向新栈顶。
所以想要将ax中的数据用栈放入10000H处,则要把sp设置为2;
pop指令的执行过程
(1)将SS:SP指向的内存单元处的数据送入ax中;
(2)SP=SP+2,SS:SP指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
注意:
出栈后,SS:SP指向新的栈顶1000EH,pop操作前的栈顶元素,1000CH处的2266H依然存在,但是,它已不在栈中。
当再次执行push等入栈指令后。SS:SP移至1000CH,并在里面写入新的数据,它将被覆盖。

3.8栈顶越界的问题

SS:SP只记录了栈顶的地址,依靠SS和SP可以保证在入栈和出栈时找到栈顶。
可是,如何能够保证在入栈、出栈时,栈顶不会超出栈空间?
会,修改栈之外的内存
push,pop指令都可以造成栈顶越界。
这是危险的:
因为我们既然将一段空间安排为栈,那么在栈空间之外的空间里很可能存放具有其他用途的数据、代码等,这些数据、代码可能时我们自己程序中的,也可能时别的程序中的。(毕竟一个计算机系统并不是只有我们自己的程序在运行)

CPU中有记录栈顶上限和下限的寄存器,我们可以通过填写这些寄存器来指定栈空间的范围,然后,CPU在执行push指令的时候检测栈顶上限寄存器,在执行pop指令的时候靠检测栈顶下限寄存器保证不会越界。
实际情况:8086CPU中并没有这样的寄存器。
所以8086CPU不保证对栈的操作不会越界。

3.9 push、pop指令

push和pop指令是可以在寄存器和内存之间传输数据的。
栈和内存
栈空间当然也是内存空间的一部分,它只是一段可以以一种特殊的方式进行访问的内存空间。
push和pop指令格式(1)
push 寄存器:将一个寄存器中的数据入栈
pop 寄存器:出栈,用一个寄存器接受出栈的数据
例如:push ax
pop bx
push和pop指令的格式(2)
push段寄存器:将一个段寄存器中的数据入栈
pop段寄存器:出栈,用一个段寄存器接受出栈的数据
例如:push ds
pop es
(段寄存器都是以s结尾的,通用寄存器都是x结尾的)
push、pop指令的格式(3)

  • push内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位的16bit)

  • pop内存单元:出栈,用一个内存字单元接收出栈的数据
    例如:push [0](ds)
    pop [2](ds:2)
    指令执行时,CPU要知道内存单元的地址,可以在push、pop指令中给出内存单元的偏移地址,段地址在指令执行时,CPU从ds中取得。
    总结:

  • push、pop实质上是一种内存传送指令,可以在寄存器和内存之间传送数据,与mov指令不同的是,push和pop指令访问的内存单元的地址不是在指令中给出的,而是由SS:SP指出的。

  • 同时,push和pop指令还要改变SP中的内容。

  • 执行push时:

  • 先改变SP,后向SS:SP处传送。

  • 执行pop时:

  • 先读取SS:SP处的数据,后改变SP。
    注意:

  • push、pop等栈操作指令,修改的只是SP。也就是说,栈顶的变化范围最大为:0~FFFFH。(16位CPU)

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

  • 8086CPU只记录栈顶,栈空间的大小我们要自己管理。

  • 用栈来暂时存储以后要恢复的寄存器内容时,寄存器出栈顺序要和入栈时相反

3.10栈段

  • 前面讲过,对于8086CP机,在编程时,我们可以根据需要,将一组内存单元定义为一个段。
  • 我们可以将长度为N(N<=64K)的一组地址连续、起始地址为16的倍数的内存,当作栈来用,从而定义了一个栈段。
  • 问题:
  • 如果我们将10000H~1FFFFH这段空间当作栈段,初始状态是空的,此时,SS=1000H,SP=?
  • 我们将10000H~1FFFFH这段空间当作栈段,SS=1000H,栈空间大小为64KB,栈最底部的字单元地址为1000:FFFE。
  • 任意时刻SS:SP指向栈顶,当栈中只有一个元素的时候,SS=1000H,SP=FFFEH。
  • 栈为空,就相当于栈中唯一的元素出栈,出栈后,SP=SP+2。
  • SP原来为FFFEH,加2后SP=0,所以当栈为空的时候,SS=1000H,SP=0。
  • 换个角度看
  • 任意时刻,SS:SP指向栈顶元素,当栈为空的时候,栈中没有元素,也就不存在栈顶元素,所以SS:SP只能指向栈的最底部单元下面的单元,该单元的偏移地址为栈最底部子单元的地址为1000:FFFE,所以栈空时,SP=0000H.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值