第二章
寄存器
CPU的概述:运算器;逻辑控制器;寄存器等器件组成,这些器件靠内部总线相连。(区别:1.内部总线实现CPU内部各个器件之间的联系。2.外部总线实现CPU和主板上其他器件的联系。)
寄存器概述:
2.1通用寄存器:AX BX CX DX。
8086CPU所以的寄存器都是16位的(15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0),可以存放两个字节。
例:18
二进制表示10010
AX 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0
一个16位寄存器可以存储一个16位的数据
最多可以存2^16-1
AX可以分为AH(高位)(8-15)和AL(低位)(0-7)
其他的同理
目的是为了兼容之前的系统
2.2字在寄存器中的存储
2.3汇编指令(汇编的指令不分大小写)
汇编指令 控制cpu完成的操作 用高级语言的语法描述
mov ax,18 将18送入ax ax=18
mov ah,78 将78送入ah ah=78
add ax,8 将寄存器ax中的数值加上8 ax=ax+8
mov ax,bx 将寄存器bx的数据送入寄存器ax ax=bx
add ax,bx 将ax,bx中内容相加,结果存在ax ax=ax+bx
2.4物理地址
cpu访问内存单元时要给出内存单元的地址。所有的内存单元构成的存储空间是一个一维的线性空间。
我们将这个唯一的地址称为物理地址
2.5 16位结构的cpu
特征
1:运算器一次最多可以处理16位的数据。
2:寄存器的最大宽度位16位。
3:寄存器和运算器之间的通路是16位的。
2.6 8086cpu给出物理地址的方法
8086cpu采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址
地址加法器合成物理地址的方法:
物理地址=段地址*16+偏移地址
2.8段的概念
内存并没有分段,段的划分来自于cpu,由于8086cpu用”(段地址*16)+偏移地址 =物理地址“的方式给出内存单元的物理地址,使得我们可以用分段的方式来管理内存。
CPU访问内存单元时,必须向内存提供内存单元的物理地址。
8086cpu在内部用段地址和偏移地址移位相加的方法形成最终的物理地址。
2.9段寄存器
段寄存器就是提供段地址的
2.10cs与ip
cs和ip是8086cou中最关键的寄存器,它们指示了cpu当前要读取指令的地址。
cs为代码段寄存器。
ip为指令指针寄存器。
例8086pc工作过程的简要概述
1:从cs:ip指向内存单元读取指令,读取的指令进入指令缓冲器;
2:ip=ip+所读取指令的长度,从而指向下一条指令;
3;执行指令,转到步骤1,重复这个过程。
在8086cpu加电启动或复位后(即cpu刚开始工作时)cs和ip被设置为cs=ffffh,ip=0000h,
即在8086pc机刚启动时,cpu从内存ffff0h单元中读取指令执行。
ffff0h单元中的指令是8086pc机开机后执行的第一条指令。
在任何时候,cpu将cs,ip中的内容当成指令的段地址和偏移地址,用他们合成指令的物理地址,到内存中读取指令码,执行。
如果是,内存中的一段信息曾被cpu执行过的话,那么,它所在的内存单元必然被cs:ip指向过。
2.11如何修改cs,ip的值
mov不能改变cpu的值、
有专门的转移指令
同时修改cs,ip的内容:jmp:功能:用指令中给出的段地址修改cs,偏移地址修改ip。
jmp段地址:偏移地址
jmp 2AE3:3 跑到2AE3:3
jmp 3:0B16
仅修改ip的内容:jmp某一合法寄存器
jmp ax(类似于movIp,ax)
jmp bx
功能:用寄存器中的值修改ip
2.12代码段
如何使得代码段中的指令被执行呢?
将一段内存当作代码段,仅仅是我们在编程时的一种安排,cpu并不会由于这种安排,就自动地将我们定义的代码段中的指令当作指令来执行。
cpu只认被cs:ip指向的内存单元中的内容为指令
所以要将cs,ip指向所定义的代码段中的第一条指令的首地址
查cpu和内存,用机器指令和汇编指令编程
Debug:是DOS,Windows一种调试工具。使用它,可以查看cpu各种寄存器中的内容,内存的情况和在机器码级跟踪程序的运行。
debug命令;
用debug的R命令查看和改变cpu寄存器的内容;
D命令查看内存中的内容;
E命令改写内存中的内容;
U命令将内存中的机器指令翻译成汇编指令;
T命令执行一条机械指令;
A命令以回避那指令的格式在内存中写入一条机械指令。
进入
cmd的命令;输入dedug
第三章 寄存器(内存访问)
3.1:内存中字的存储
任何两个地址连续的内存单元,n号单元和n+1号单元,可以将他们看成两个内存单元,也可以看成一个地址为n的字单元中的高位字节单元和低位字节单元
3.2ds和【address】
cpu要读取一个内存单元的时候,必须先给出这个内存单元的地址;
8086cou中有一个ds寄存器,通常用来存放要访问的数据的段地址;
已知的mov指令可完成的两种传送功能:
[address]表示一个偏移地址为address的内存单元
(1)将数据直接送入寄存器;
(2)将一个寄存器中的内容送入另一个寄存器中。
除此之外,mov指令还可以将一个·内存单元中的内容送入一个寄存器中。
mov指令的格式:
mov 寄存器名,内存单元地址
”【...】“表示一个内存单元,"【...】"中的0表示内存单元的偏移地址。
执行指令时,8086cou自动取ds中的数据为内存单元的段地址。
8086cpu不支持将数据直接送入段寄存器的操作,ds是一个段寄存器。
数据》通用寄存器》段寄存器
3.3字的传送
3.4mov,add,sub指令
mov的指令的几种形式:
mov寄存器,数据
mov寄存器,寄存器
mov寄存器,内存单元
mov内存单元,寄存器
mov段寄存器,寄存器
mov寄存器,段寄存器
add:
add 寄存器,数据
add寄存器,寄存器
add寄存器,内存单元
add内存单元,寄存器
sub寄存器,数据
sub寄存器,寄存器
sub寄存器,内存单元
sub内存单元,寄存器
(他们不可以对段寄存器进行操作)
3.5数据段
将一组长度为n(<=64k),地址连续,起始地址为16的倍数的内存单元当作专门存储数据的内存空间,从而定义了一个数据段
3.6栈
栈是一种具有特殊的访问方式的存储空间。他的特殊性就在于,最后进入这个空间的数据,最先出去
栈有两个基本操作:入栈和出栈。
入栈:将一个新的元素放入栈顶
出栈:从栈顶取出一个元素。
栈顶的元素总是最后入栈,需要出栈时,又最先从栈中取出
入栈和出栈的指令
push(入)
pop(出)
8086cpu中有两个寄存器:
段寄存器ss 存放栈顶的段地址
寄存器sp 存放栈顶的偏移地址
任意时刻,ss:sp指向栈顶元素。
push指令的执行过程
push ax
(1)sp=sp-2;
(2)将ax中的内容送入ss;sp指向的内存单元处,ss;so此时指向新栈项
pop同理(push的逆运算· )
如果初始状态栈是空的,此时,ss=1000h,sp=0010h
3.8栈顶越界的问题
ss和sp只记录了栈顶地址,依靠ss和sp可以保证在入栈和出栈时找到栈顶。
可是,如何能够保证在入栈,出栈时,栈顶你会超出栈的空间?(栈越界是危险的)
8086cpu的工作机理,只考虑当前情况:
当前栈顶在和何处:
当前要执行的指令是哪一条
3.9push,pop指令是可以在寄存器和内存至今传送数据的
pop ax
(1)将ss:sp指向内存单元处的数据送入ax中;
(2)sp=sp+2,ss,sp指向当前栈顶下面的单元,以当前栈顶下面的单元为新的栈顶。
push和·pop指令的格式(1)
push寄存器:将一个寄存器中的数据入栈
pop寄存器:出栈,用一个寄存器接收出栈的数据
(2)
push段寄存器:将一个段寄存器中的数据入栈
pop段寄存器:出栈,用一个段寄存器接收出栈的数据
(3) push内存单元:将一个内存单元处的字入栈(栈操作都是以字为单位)
pop内存单元:处栈,用一个内存字单元接收出栈的数据
指令执行时,cpu要知道内存单元的地址,可以在push,pop指令中给出内存单元的偏移地址,段地址在指令执行时,cpu从ds中取得
3.10栈段
栈为空,就相当于栈中唯一的元素出,出栈后,sp=sp+2