第二章 寄存器


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(只读)的内存段


真的太多了,码了一天。

寄存器---汇编学习笔记相关推荐

  1. 标记寄存器---汇编学习笔记

    标记寄存器 CPU内部的寄存器中,有一种特殊的寄存器(对于不同的处理机,个数和结构都可能不同)具有以下3种作用. (1)用来存储相关指令的某些执行结果. (2)用来为CPU执行相关指令提供行为依据. ...

  2. 汇编学习笔记——汇编指令

    目录 汇编指令 nop指令 mov.add.sub指令 adc.sbb指令 and.or指令 移位指令 逻辑左/右移指令 循环左/右移指令 算术左/右移指令 带进位循环左/右移指令 inc指令 pus ...

  3. 汇编学习笔记——伪指令

    目录 伪指令 段定义 结束标记 段关联标记 数据定义 标号 offset指令 seg指令 地址标号 数据标号 代码分段 程序标识 多文件系统 字符输入 重复定义 注释 重复汇编伪指令 伪指令汇总 伪指 ...

  4. 汇编学习笔记:对抗反汇编实验2019092801

    汇编学习笔记:对抗反汇编实验2019092801 实验描述 实验环境 实验过程 实验结论 实验描述 使用相连的jz和jnz指令跳转到紧接着jnz指令的call指令的第二个字节.call指令实际上无效. ...

  5. GNU C内嵌汇编学习笔记

    前文所述,只是针对汇编格式的整理,本文将使用coreboot项目代码对其进行实例化.以方便.清晰了解到如何在C语言里使用内嵌汇编的方法.同样地,网络上也有众多文章涉及到这方面,所以本文更多是归纳总结. ...

  6. 寄存器(内存访问)---汇编学习笔记

    寄存器(内存访问) 序言 第二章,我们主要从CPU如何执行指令的角度讲解了8086CPU的逻辑结构.形成物理地址的方法.相关的寄存器以及一些指令. 这一章,我们从访问内存的角度继续学习几个寄存器. 3 ...

  7. ICS汇编学习笔记——8086中的寄存器

    程序执行两大部件:总线接口单元(BIU) 执行单元(EU) 指令和数据都在内存中 BIU与EU是并行执行的 BIU负责取指令和存取操作数 EU负责译码和指令的执行 8086的8个16位通用寄存器 AX ...

  8. 汇编学习笔记1 通用寄存器和段寄存器详解

    一.通用寄存器 寄存器         编号(二进制) 编号(十进制)   64位 32位 16位 8位     累加寄存器 RAX EAX AX AL 000 0 计数寄存器 RCX ECX CX ...

  9. 第一个程序---汇编学习笔记

    第四章 第一个程序 4.1 一个源程序从写出到执行的过程 一个汇编语言程序从写到最终执行的简要过程. 编写汇编源程序 对源程序进行编译连接 执行可执行文件中的程序 如图所示: 4.2 源程序 程序代码 ...

最新文章

  1. java 枚举转byte_如何在java中将一个枚举转换为另一个枚举?
  2. 彻底搞懂浏览器Event-loop
  3. bootstrap-table页码ALL显示为NAN
  4. [OSDI 16] Wukong : 基于RDMA的高并发、快速的分布式RDF Graph Query系统
  5. 容易答错的java面试题_Java程序员面试中最容易答错的8道面试题,你中招了吗?...
  6. 【机器学习】异常检测算法之(HBOS)-Histogram-based Outlier Score
  7. VR开发中性能问题—OculusWaitForGPU
  8. mysql8.0版本的服务器名称_Linux服务器配置-VSFTP服务配置(六)
  9. python爬虫外快_利用Python爬虫轻松挣外快的几个方法(值得收藏)
  10. ubuntu下tftp服务器环境搭建
  11. java 压缩js css_Java使用YUI Compressor压缩JS/CSS文件
  12. SWAT模型学习小技巧(前言)
  13. 福特dms系统服务器,长安福特DMS使用规范.pdf
  14. 剑指offer_33:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
  15. 张宇基础30讲——第6讲-中值定理
  16. 机器学习方法之非线性回归( Logistic Regression)
  17. 港股通不得不了解的汇率问题
  18. python实现简单舒尔方格
  19. stp转obj, stp转stl转换小工具
  20. [软件]Safe3 Web漏洞扫描系统企业版v10.1 破解版

热门文章

  1. dedecms原理及使用
  2. 获取jar包内部的资源文件
  3. ElasticSearch2.3.1环境搭建哪些不为人知的坑
  4. Spring 3.0 注解注入详解
  5. 进入Windows的世界
  6. 感受野receptive field个人理解
  7. Deep Learning学习 之 CNN代码解析(MATLAB)
  8. 吴恩达 coursera AI 专项二第三课总结+作业答案
  9. Python学习笔记:常用内建模块6 (urllib)
  10. Python学习笔记:正则表达式