寄存器---汇编学习笔记

第二章 寄存器


2.0 寄存器的绪论

一个典型的CPU由运算器、控制器、寄存器(CPU工作原理)等器件构成。内部总线实现 CPU 内部各个器件之间的联系,外部总线实现CPU和主板其他器件的联系

在CPU中(下列重要内容)

  • 运算器进行信息处理;
  • 寄存器进行信息存储;
  • 控制器控制各个器件进行工作;
  • 内部总线连接各种器件,在它们之间进行数据的传送。

对于汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中与程序员可以用指令读写的部件
不同的CPU寄存器个数结构不相同的。


2.1 通用寄存器

8086CPU的所有寄存器都是16位的
通用寄存器:AX、BX、CX、DX.
一个16位寄存器的逻辑结构:
这里写图片描述
8086CPU的上一代CPU中的寄存器都是8位的。
为了保证兼容,8086的16bit寄存器分为两个独立8bit寄存器

  • AX可分为AH和AL.
  • BX可分为BH和BL.
  • CX可分为CH和CL.
  • DX可分为DH和DL.

如图,AX的高8bit是AH,低8bit是AL:
这里写图片描述

一个8bit寄存器所能存储的数据的最大值为255


2.2 字在寄存器中的存储

  • 字节(byte):一个字节有8个bit组成,可以存在8位寄存器中
  • 字(word):一个字由两个字节组成,这两个字节分别称为高位字节低位字节
    这里写图片描述

一个字可以存在一个16位寄存器中,这个字的高位字节和低位字节自然就存在这个寄存器的高8位寄存器和低8位寄存器中。一个word数据20000的例子,如图:
这里写图片描述
其中,信息本身是二进制数据,而不是十进制数据,别搞混
再强调一遍,信息本身就是二进制数据


2.3 初识汇编指令

汇编指令 控制CPU完成的操作 用高级语言的语法描述
mov a,b 将b的数据送入a中 a = b
add a,b 将a+b的数据送入a中 a = a+b

a代表寄存器,b代表数据或者寄存器

问题2.1:指令执行后AX中的数据是多少?

mov ax,4E20H    ;AX=4E20H   
add ax,1406H    ;AX=6226H
mov bx,2000H    ;BX=2000H
add ax,bx       ;AX=8226H
mov bx,ax       ;BX=8226H
add ax,bx       ;AX=044CH

指令执行后AX中的数据为 004CH
问题2.2:指令执行后AX中的数据是多少?

MOV AX,001AH    ;AX=001AH
MOV BX,0026H    ;BX=0026H
ADD AL,BL       ;AX=0040H
ADD AH,BL       ;AX=2640H
ADD BH,AL       ;BX=4026H
MOV AH,0        ;AX=0040H
MOV AL,85H      ;AX=00C5H
ADD AL,93H      ;AX=0158H

指令执行后AX中的数据为 0158H

检测点 2.1
(1) 写出每条汇编指令执行后相关寄存器中的值。

MOV AX,62627    ;AX=F4A3H
MOV AH,31H      ;AX=31A3H
MOV AL,23H      ;AX=3123H
ADD AX,AX       ;AX=6246H
MOV BX,826CH    ;BX=826CH
MOV CX,AX       ;CX=6246H
MOV AX,BX       ;AX=826CH
ADD AX,BX       ;AX=04D8H
MOV AL,BH       ;AX=0482H
MOV AH,BL       ;AX=6C82H
ADD AH,AH       ;AX=D882H
ADD AL,6        ;AX=D806H
ADD AL,AL       ;AX=D80CH
MOV AX,CX       ;AX=6246H

(2) 只能使用目前学过的汇编指令,最多使用4条指令,编程计算2的4次方。

MOV AX,2        ;AX = 2
ADD AX,AX       ;AX = 4
ADD AX,AX       ;AX = 8
ADD AX,AX       ;AX = 16

2.4 物理地址

所有的内存单元构成的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有一个唯一的地址,称为物理地址
CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址


2.5 16位结构的CPU

8080、8085是8位机,8086是16位机。

16位结构的CPU具有的结构性质

  • 运算器一次最多可以处理16位的数据;
  • 寄存器的最大宽度位16位;
  • 寄存器和运算器之间的通路为16位。

8086是16位结构的CPU,也就是说,能够一次性处理、传输、暂时存储的信息最大长度是16位的。


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

8086CPU有20位地址总线,可以传送20位地址,达到1MB的寻址能力。8086CPU是16位结构,在内部一次性处理、传输、暂时存储的地址为16位。从表面上看CPU只能寻址64KB。
8086CPU采用一种内部用两个16位地址合成的方法来形成一个20位的物理地址

如图:
这里写图片描述
当8086CPU要读写内存时

  • CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个称为偏移地址
  • 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
  • 地址加法器将两个16位合成为一个20位的物理地址
  • 地址加法器通过内部将20位物理地址送入输入输出控制电路
  • 输入输出控制电路将20位物理地址送上地址总线
  • 20位物理地址被地址总线传送到存储器

地址加法器采用物理地址 = 段地址x16+偏移地址

地址加法器工作过程(图中数据皆用十六进制表示):
这里写图片描述
由段地址x16引发的讨论
“段地址x16”有一个更为常用的说法是左移4位。
一个例子:

左移位数 二进制 十六进制 十进制
0 10B 2H 2
1 100B 4H 4
2 1000B 8H 8
3 10000B 10H 16
4 100000B 20H 32

观察上面移位数和各种进制数据的关系,我们可以发现

  • 一个数据的 二进制形式左移 1位,相当于该数据 乘以2
  • 一个数据的 二进制形式左移 N位,相当于该数据乘以2的N次方;
  • 地址加法器如何完成段地址x16的运算?就是将以二进制形式存放的段地址左移4位

不难得出,一个数据的十六进制形式左移1位,相当于乘以16


2.7 “段地址x16+偏移地址=物理地址”的本质含义

本质含义是:CPU在访问内存时,用一个基础地址(段地址x16)和偏移地址相加,给出内存单元的物理地址。(可以理解为从基础地址出发+偏移量 = 你要去的目的地)


2.8 段的概念

实际上,内存并没有分段,段的划分来自于CPU
我们可以在逻辑上将内存“分段”,如图
这里写图片描述
编程时,可以根据需要,将若干个地址连续的内存单元看做一个段(注意:段地址一定是16的倍数,一个段的长度最大为64KB)。


内存单元地址小结

(1)观察下面的地址,你有什么发现?

物理地址 段地址 偏移地址
21F60H 2000H 1F60H
21F60H 2100H 0F60H
21F60H 21F0H 0060H
21F60H 21F6H 0000H
21F60H 1F00H 2F60H

结论:CPU可以用不同的段地址(SA)和偏移地址(EA)形成同一个物理地址

(2)如果给定一个段地址,仅通过变化偏移地址来寻址最多可定位多少个内存单元?

结论:如果给定一个段地址,仅通过变化偏移地址来寻址最多可定位64KB个内存单元

数据在 21F60H 内存单元中,CPU 表示 形式为 2000:1F60 单元中。

检测点 2.2
(1)给定段地址为0001H,仅通过变化偏移地址寻址,CPU的寻址范围为 0001:00000001:FFFF
(2)有一数据存放在内存 20000H 单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为 1001H ,最大为 2000H


2.9 段寄存器(提供段地址)

8086CPU有4个段寄存器:CS、DS、SS、ES


2.10 CS和IP

CS为段寄存器,IP为指令指针寄存器

一个例子(展示CPU执行指令原理,比较长)
这里写图片描述
从下面一系列的图展示过程。
下面,首先初始化
这里写图片描述
将CS、IP的内容送入地址加法器
这里写图片描述
地址加法器将物理地址送入输入输出控制电路
这里写图片描述
输入输出控制电路将物理地址送到地址总线
这里写图片描述
内存中存放的机器指令被送入CPU
这里写图片描述
输入输出控制电路将指令送入指令缓冲器
这里写图片描述
IP中的值自动增加,以使CPU可以读取下一条指令
这里写图片描述
执行控制器执行指令
这里写图片描述
指令被执行后,AX内容发生了变化
这里写图片描述
同上过程,读取下一条指令
这里写图片描述
这里写图片描述
再读取下一条!
这里写图片描述
又读取一条!
这里写图片描述
到此为止,4条指令执行历程结束!

通过上面的例子,8086CPU的工作过程可以简要描述如下。

  1. 从CS:IP指向的内存单元读取指令,读取的指令进入缓冲器。
  2. IP=IP+所读取指令的长度,从而指向下一条指令。
  3. 执行指令。转到步骤1,重复这个过程。

8086CPU加电启动或复位后,CS和IP被设置为CS=FFFFH,IP=0000H(重要,也就是说FFFF0H是8086PC机开机后执行的第一条指令)


2.11 修改CS、IP的指令

CPU从何处执行指令?
显然,由CS、IP中的内容决定的
我们如何改变CS、IP的值呢?
8086CPU提供相应的指令

我们在初步了解汇编指令的时候使用过 mov 指令,那我们能够使用mov指令来修改CS、IP的内容吗?
答案是不可以的,因为8086CPU的mov指令没有提供这样的功能

我们将用最简单的可以修改CS、IP的指令: jmp 指令
使用方式形如: jmp 段地址 : 偏移地址。这个指令的功能是修改CS和IP的值
还有另一种修改方式: jmp 某一合法寄存器。这个指令的功能是修改IP的值

问题 2.3
这里写图片描述
指令执行序列如下:

  1. MOV AX,6622H
  2. JMP 1000:3
  3. MOV AX,0000
  4. MOV BX,AX
  5. JMP BX
  6. MOV AX,0123H
  7. 返回第三步

2.12 代码段

对于8086PC机,在编程时,可以将一组内存单元定义为一个段。我们可以将长度为 N(N<=64KB) 的一组代码,存在一组地址连续、起始地址为16的倍数的内存单元中。我们可以认为,这段内存是用来存放代码的,从而定义了代码段

例如:

MOV AX,0000H    ;(B8 00 00)
ADD AX,0123H    ;(05 23 01)
MOV BX,AX       ;(8B D8)
JMP BX          ;(FF E3)

这段长度为10个字节的指令,存放在123B0H~123B9H的一组内存单元中,我们就可以认为,123B0H~123B9H这段内存时用来存放代码的,是一个代码段,它的段地址为123BH,长度为10个字节。
这段代码如何被执行呢?
显然,只要将CS = 123BH,IP = 0000H即可。


2.9~2.12 小结

  1. 段地址在8086CPU的段寄存器中存放;
  2. 8086CPU有4个段地址;
  3. CS存放指令的段地址,IP存放指令的偏移地址(CPU将 CS:IP 指向的内容当做指令执行);
  4. 8086CPU的工作过程:
    1. 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器;
    2. IP指向下一条指令;
    3. 执行指令。(转到步骤1,重复这个过程)
  5. 8086CPU提供转移指令修改CS、IP的内容。

检测点 2.3
下面的3条指令执行后,CPU几次修改IP?都是在什么时候?最后IP中的值是多少?

MOV AX,BX   ;AX=BX
SUB AX,AX   ;AX=0
JMP AX      ;IP=0

答案:一次修改 IP,在 JMP AX 的时候,最后 IP 为0000H


实验1 查看CPU和内存,用机器指令和汇编指令编程


1.预备知识:Debug的使用

(1)什么是Debug?
Debug是 DOS、Windows 都提供的实模式(8086 方式)程序的调试工具。使用它,可以查看CPU各种寄存器中的内容、内存的情况和在机器码级跟踪程序的运行。

(2)我们用到的Debug功能。

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

Debug的命令比较多,共有20多个,但这6个命令是和汇编学习密切相关的。在以后还有用到一个P命令

(3)进入Debug。
Debug是在DOS方式下使用的程序。我们在进入Debug前,应先进入到DOS方式。
用以下方式可以进入DOS。

  1. 重启计算机,进入DOS方式,此时进入的是实模式的DOS。
  2. 在Windows中进入DOS方式,此时进入的是虚拟8086模式的DOS。

在这里,我用的是 实验楼 的环境。这样降低了学习成本

(4)用 R命令 查看、改变CPU寄存器的内容。
如下,成功显示了寄存器的内容
这里写图片描述
如下,成功修改了AX寄存器的内容
这里写图片描述
我们注意到 DS:0000 = 0 以后的章节会介绍。还看到了最下面一行出现的 TEST …的汇编指令
可以用 R命令 修改CS和IP的内容。

(5)用Debug的 D命令 查看内存中的内容。
用Debug的D命令,可以查看内存中的内容,D命令的格式比较多。
可以用:D 段地址 : 偏移地址,如下。
这里写图片描述
使用D命令,Debug将输出3部分内容,如下。

  • 中间是从指定地址开始的128个内存单元的内容,用十六进制的格式输出。每行的输出从16的整数倍的地址开始,最多输出16个单元的内容。
  • 左边是每行的起始地址。
  • 右边是每个内存单元中的数据对应的可显示的 ASCII 码字符。

(6)用 Debug 的 E命令 改写内存中的内容。

E 10        ;修改当前数据段10H号单元内容
E ES:100    ;修改附加段100H号单元内容
D ES:100    ;查看一下100H单元的内容是否修改了

这里写图片描述

(7)用E命令向内存中写入机器码,用U命令查看内存中机器码的含义,用T命令执行内容从中的机器码。
E命令其他用法
这里写图片描述
这里写图片描述

编写一个如下代码的汇编程序

MOV AX,0001     ;B80100
MOV CX,0002     ;B90200
ADD AX,CX       ;01C8

编写代码如下:
这里写图片描述
修改CS、IP寄存器
这里写图片描述
使用T命令执行汇编指令
这里写图片描述
观察以上所有图片寄存器的变化(眼睛都花了)

(8)用Debug的 A命令 以汇编指令形式在内存中写入机器指令。
如图。
这里写图片描述
从最后一行可以看出,内存1000H段的内容已经被修改成功

最后,在一张命令表格吧。

命令 说明
R命令 查看、修改CPU
D命令 查看内存中的内容
E命令 修改内存中的内容
U命令 将内存中的内容解释为机器指令和对应的汇编指令
T命令 执行CS:IP指向的内存单元处的指令
A命令 以汇编指令的形式向内存中写入指令

2. 实验任务

(1)使用 Debug,将下面的程序段写入内存,逐条执行,观察每条指令执行后,CPU中相关寄存器中内容的变化。

汇编指令        机器码     
MOV AX,4E20H    ;B8 20 4E
ADD AX,1416H    ;05 16 14
MOV BX,2000H    ;BB 00 20
ADD AX,BX       ;01 D8
MOV BX,AX       ;89 C3
ADD AX,BX       ;01 D8
MOV AX,001AH    ;B8 1A 00
MOV BX,0026H    ;BB 26 00
ADD AL,BL       ;00 D8
ADD AH,BL       ;00 DC
ADD BH,AL       ;00 C7
MOV AH,0        ;B4 00      
ADD AL,BL       ;00 D8
ADD AL,9CH      ;04 9C

Debug下用A命令输入汇编指令:
这里写图片描述
再用D命令查看是否输入汇编指令到内存:
这里写图片描述
在使用R命令查看和修改CS、IP的值,修改成代码段的开始位置:
这里写图片描述
最后,T命令执行,自行实验观察步骤。
整个过程只要观察AX和BX就好,最后AX=0002,BX=4026

(2)将下面3条指令写入从 2000:0 开始的内存单元中,利用这3条指令计算2的8次方。

mov ax,1
add ax,ax
jmp 2000:0003

分析,我们知道 mov ax,1 占了3个内存单元。所以我们代码段的开始位置为2000H

如下(要算2的8次方,add ax,ax,这个跟算法的快速幂一样,我们只要add ax,ax四次就行,因为ax初始化为1):
这里写图片描述

(3)查看内存中的内容。
PC机主板上的ROM中写有一个生产日期,在内存 FFF00H~FFFFFH 的某几个单元中,请找到这个生产日期,在内 FFF00H~FFFFFH 的某几个单元中,请找出这个生产日期并试图改变它。

显然,用D FFF0 : 0000 L 100就可以得出答案,如下
这里写图片描述

(4)向内存从B8100H开始的单元中填写数据,如:

-e B8100:0000 01 01 02 02 03 03 04 04

发现:数据没有被改变,为什么呢?
原因:我们阅读第一章的时候,我们知道我们将所有内存当做一个逻辑连续的内存。而B810H地址段ROM(只读)的内存段
这里写图片描述


真的太多了,码了一天。

猜你喜欢

转载自blog.csdn.net/qq_37340753/article/details/80935423