《汇编语言》笔记

《汇编语言(第三版)》笔记

1.1机器语言

1.机器语言:机器指令的合集
2.机器指令:一列二进制数字。
3.计算机将指令转变为相应的一列高低电平,以驱动计算机的电子器件进行运算。 (此处计算机指可以执行机器指令,进行运算的机器。)
4.不同的CPU(Central Processing Unit,中央处理单元,一种微处理器)由于硬件设计和内部结构的不同,由不同的电平脉冲控制,每一种微处理器都有自己的机器指令集(机器语言)

1.2汇编语言的产生

由于机器语言的难于辨别和记忆,汇编语言产生了.

汇编语言是直接在硬件之上工作的编程语言

汇编指令与机器指令的差别在于指令的表达方法汇编指令是机器指令便于记忆的书写格式 (相当于汇编指令是给人看的,机器指令是给计算机看的,两者呈对应关系)

eg: 将寄存器BX的内容放入AX中

机器指令:1000100111011000

汇编指令:mov ax,bx

寄存器简单来说是在CPU中可以存储数据的器件,一个CPU有多个寄存器

编译器:将汇编指令转换成机器指令的翻译程序在这里插入图片描述

1.3汇编语言的组成

1.汇编指令:机器码的助记符,有对应的机器码

2.伪指令:没有对应的机器码,由编译器执行,计算机并不执行(计算机不认识,编译器认识)

3.其他符号:如 +、-、*、/等,没有对应的机器码,由编译器识别

汇编语言的核心是汇编指令,它决定了汇编语言的特性

1.4存储器

CPU是计算机的核心部件,控制整个计算机的运作并进行运算

存储器:存放让CPU工作的指令和数据,即我们口中的内存

在一台PC机中,内存的作用仅次于CPU。离开内存,性能再好的CPU也无法正常工作。就像再聪明的大脑,没有记忆也无法进行思考;性能再好的车,没有车轮也动不了

磁盘信息->内存->程序

1.5指令和数据

指令和数据是应用上的概念

在内存或磁盘上,指令和数据没有任何区别,都是二进制信息。

相同的二进制在不同的地方由不同的意义

eg:

1000100111011000 ->89D8H(数据)

1000100111011000 ->mov ax,bx(程序)

1.6存储单元

存储器被划分成若干个存储单元,每个存储单元从0开始编号
微型存储器的一个存储单元可以存储一个Byte,8个二进制位
微机存储器的容量是以字节为最小单位进行计算的

          1Byte=8bit      1TB=2^10GB=2^20MB=2^30KB=2^40B                              

在这里插入图片描述

1.7CPU对存储器的读写

一台微机中不只有存储器一种器件,CPU读取数据时,要指明对哪一个器件进行操作,进行哪种操作;从内存中读数据,要指定存储单元地址

  • CPU要想进行数据的读写,必须和外部器件(准确来说是芯片)进行三类信息的交互
  • 存储单元的地址(地址信息)
  • 器件的选择,读或写命令(控制信息)
  • 读或写的数据(数据信息)

CPU通过导线将地址、数据和控制信息传到存储器芯片,在计算机中有专门连接CPU和其他芯片的导线,通常称为总线

总线:

物理上:一根根导线的合集

逻辑上:地址总线、控制总线、数据总线(根据传送信息的不同划分)
在这里插入图片描述

地址总线确定地址->控制总线发送指令->数据总线完成数据的传输

1.8地址总线

  • 地址总线上能传送多少个不同的信息,CPU就能对多少个存储单元进行寻址
  • 一个CPU有N根地址线,即这个CPU的地址总线的宽度为N。最多可寻找2^N个内存单元
  • 地址总线的宽度决定了CPU的寻址能力

在这里插入图片描述

1.9数据总线

  • CPU与内存或其他期间之间的数据传输通过数据总线进行。

  • 数据总线的宽度决定CPU和其他器件进行数据传送时的速度。

    eg:8根数据总线一次可传送一个字节(8个二进制数据) 8088CPU :8根 8086CPU:16根

1.10控制总线

  • CPU对外部器件的控制是通过控制总线来进行的
  • 控制总线是一些不同控制线的合集
  • 控制总线的宽度决定CPU对系统中其他器件的控制能力

"读信号输出"控制线负责CPU向外传送读信号,CPU向该控制线上输出低电平表示将要读取数据;

"写信号输出"控制线负责传送写信号

监测点1.1

(1)1个CPU的寻址能力是8KB,那么它的地址总线的宽度为 __13__

8KB=2^13B

一根地址总线对应一个存储单元是1B

N根地址线,地址总线宽度为N,最多可寻2^N个内存单位

N=13

(2)1KB的存储器有1024个存储单元,存储单元的编号从01023

(3)1KB的存储器可以存储8192bit,1024Byte

1个存储单元->1B,1KB=1024B 编号从0开始

1B=8bit 1KB=1024*8=8192bit

(4)1GB、1MB、1KB分别是2^30 、2^20、 2^10 Byte

(5)8080、8088、80286、80386的地址总线宽度分别是16根、20根、24根、32根,则他们的寻址能力分别为 64KB、1MB、16MB、4GB

拿8080的16根举例:16根总线,最多可寻2^16个内存单元

2^16 B=2^6KB=64KB

2^20B=1MB

2^24 B=2^4MB=16MB

2^32B=4GB

(6)8080、8088、8086、80286、80386的地址总线宽度分别是8根、8根、16根、16根、32根,则他们一次可以传送的数据为 1B、1B、2B、2B、4B

数据总线8根1B

(7)从内存中读取1024字节的数据,8086至少要读 512次,80386至少要读 256次

8086一次2B,80386一次4B

共1024B

(8)在存储器中,数据和程序以二进制形式存放。

1.11 内存地址空间(概述)

什么是内存地址空间呢?

举例说:一个CPU的地址总线宽度是10,那么可以寻址1024个内存单元,而这1024个可寻到的内存单元就构成这个CPU的内存地址空间

1.12主板

每一台PC机都有一个主板,主板上有核心器件和一些主要器件(CPU,存储器,外围芯片组,扩展插槽等),它们通过总线(地址,数据,控制~)连接。扩展插槽上一般插有RAM内存条和各类接口卡

1.13接口卡

  • 计算机系统中,所有可用程序控制器工作设备,必须受到CPU的控制(即CPU–>应用程序–>相应工作设备);
  • CPU对外部设备(音响,显示器,打印机等)都不能直接控制
  • 直接控制外部设备的是插在扩展插槽上的接口卡
  • 扩展插槽通过总线和CPU连接,所以接口卡也通过总线通CPU进行连接
  • CPU直接控制接口卡,从而实现CPU对外设的间接控制(CPU通过总线向接口卡发送命令,接口卡根据命令控制外设)

1.14各类存储器芯片

从读写属性上可分为两类:

  • 随机存储器(RAM)

  • 只读存储器(ROM)

随机存储器可读可写,但必须带电存储,关机后存储的内容丢失;

只读存储器只能读取不能写入,关机后其中的内容不丢失。

从功能和连接上分类:

  • 随机存储器RAM

用于存放供CPU使用的绝大部分程序和数据,主随机存储器一般由装在主板上的RAM插在扩展插槽上的RAM两个位置上的RAM组成

  • 装有BIOS(Basic Input/Output System)的ROM

BIOS(基本输入输出系统)是由主板和各类接口卡厂商提供的软件系统,可以通过它利用还硬件设备进行基本的输入输出。在主板和某些接口卡上插有存储相应BIOS的ROM.eg:主板上的ROM存储着主板(系统)的BIOS,网卡上的ROM存储着显卡的BIOS和显卡上的ROM存储着显卡的BIOS

  • 接口卡上的RAM

某些接口卡需要对大批量输入、输出数据进行暂时存储,在其上装有RAM。典型的是显卡上的RAM,一般称为显存

在这里插入图片描述

1.15内存地址空间

不同存储器在物理上是独立的器件;

但他们都和CPU总线相连;CPU通过控制线对它们进行控制

CPU在操控各存储器时,把他们都当做内存来对待,把他们总的看做一个由若干存储单元组成的逻辑存储器,即我们所说的内存地址空间

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kvOXoyBR-1594394160271)(C:\Users\Huawei\Desktop\内存地址空间.png)]

1.14各类存储器芯片

从读写属性上可分为两类:

  • 随机存储器(RAM)

  • 只读存储器(ROM)

随机存储器可读可写,但必须带电存储,关机后存储的内容丢失;

只读存储器只能读取不能写入,关机后其中的内容不丢失。

从功能和连接上分类:

  • 随机存储器RAM

用于存放供CPU使用的绝大部分程序和数据,主随机存储器一般由装在主板上的RAM插在扩展插槽上的RAM两个位置上的RAM组成

  • 装有BIOS(Basic Input/Output System)的ROM

BIOS(基本输入输出系统)是由主板和各类接口卡厂商提供的软件系统,可以通过它利用还硬件设备进行基本的输入输出。在主板和某些接口卡上插有存储相应BIOS的ROM.eg:主板上的ROM存储着主板(系统)的BIOS,网卡上的ROM存储着显卡的BIOS和显卡上的ROM存储着显卡的BIOS

  • 接口卡上的RAM

某些接口卡需要对大批量输入、输出数据进行暂时存储,在其上装有RAM。典型的是显卡上的RAM,一般称为显存

在这里插入图片描述

1.15内存地址空间

  • 不同存储器在物理上是独立的器件;
  • 但他们都和CPU总线相连;CPU通过控制线对它们进行控制

CPU在操控各存储器时,把他们都当做内存来对待,把他们总的看做一个由若干存储单元组成的逻辑存储器,即我们所说的内存地址空间

在这里插入图片描述
图中,所有的物理存储器被看做一个由若干个存储单元组成的逻辑存储器,每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间

第二章 寄存器

典型的CPU由运算器、控制器、寄存器等器件构成

这些器件靠内部总线相连

内部总线实现CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系

  • 运算器:进行信息处理
  • 寄存器:进行信息的储存
  • 控制器:控制各种器件进行工作

寄存器是CPU中程序员可以用指令读写的部件,程序员通过改变各种寄存器中的内容来实现对CPU的控制(程序员通过控制寄存器控制CPU)

不同的CPU,寄存器的个数,结构不相同

8086CPU有14个寄存器且都是16位的,可存放两个字节:AX、BX、CX、DX

SI、DI SP、BP、IP CS、SS、DS、ES、PSW

2.1 通用寄存器

通用寄存器:通常用来存放一般性的数据 eg:8086CPU 的AX BX CX DX

一个16位的寄存器能存储的数据最大值是2^16-2=65535

为了兼容,8086CPU的AX BX CX DX这四个寄存器都可分为两个独立使用的8位寄存器来用

AX–>AH和AL; (H=High L=Low)

BX–>BH和BL;

CX–>CH和CL;

DX–>DH和DL;

在这里插入图片描述在这里插入图片描述
AX的低八位(0~~7)——>AL;
AX的高八位(8~15)——>AH

2.2字在寄存器中的存储

8086CPU出于对兼容性的考虑,可一次性处理量两种尺寸的数据:

  • 字节:byte 1B=8bit
  • 字:记为word,一个字两个字节,分别称为字的高位字节和低位字节
    在这里插入图片描述

2.3 几条汇编指令

在这里插入图片描述

  • 从后向前运算
  • 汇编指令或寄存器名称不区分大小写
    在这里插入图片描述在这里插入图片描述

问题2.1 执行指令后的AX是?

  • 16进制相加满16进一位

由图得知:

8226H+8226H=1044CH

AX为16位寄存器,只能UC南方4位16进制,从右向左取舍

舍去最高位1 ,所以执行指令后的AX是044CH

问题2.2,执行指令后的AX是?

在这里插入图片描述

执行add al,93H指令时 AX=00C5H

al指低8位,运算时取AX的C5H, 93H+C5H=158H

al只能存放两位16进制数据,所以高位1舍去(非彻底丢弃),执行指令后的AX=0058H

在进行数据运算或传送时,指令的两个操作对象的位数是一致的;

eg: mov ax ,bx ;

​ mov ax 18H;

​ add al 18H;

监测点2.1

(一)

(1) mov ax,62627 AX=F4A3H

62627D=F4A3H

(2)mov ah,31H AX=31A3H

31H覆盖ax中的ah部分 即F4->31

(3)mov al,23H AX=3123H

23H覆盖ax中的al部分,即A3->23

(4)add ax,ax AX=6246H

两个ax相加,3123H+3123H=6246H

(5)mov bx,826CH BX=826CH

826C覆盖bx

(6)mov cx,ax CX=6246H

ax覆盖cx cx=ax=6246H

(7)mov ax,bx AX=826CH

bx覆盖ax,ax=bx=826CH

(8)add ax,bx AX=04D8H

bx与ax相加,放入ax 826CH+826CH=104D8H,最高位1舍去

ax=04D8H

(9)mov al,bh AX=0482H

bh覆盖al,ah不受影响 ax=0482H

(10)mov ah,bl AX=6C82H

bl覆盖ah,al不受影响,ax=6C82H

(11)add ah,ah AX=D882H

两个ah相加,al不受影响

6CH+6CH=D8H ax=D882H

(12)add al,6 AX=D888H

6加到al上,ah不受影响 ax=D888H

(13)add al,al AX=D810H

两个al相加,ah不受影响 88H+88H=110H 高位1舍去

ax=D810H

(14)mov ax,cx AX=6246H

cx覆盖ax ax=cx=6246H

2.4物理地址

我们知道,CPU访问内存单元时,要给出内存单元的地址。

所有的内存单元构成的存储空间是一个一维的线性空间,每一个

内存单元在这个空间中都有唯一的地址,我们将这唯一的地址

称为物理地址。

  • CPU通过地址总线送入存储器的地址必须是一个内存单元的物理地址;

  • 在CPU向地址总线上发送物理地址之前,必须要在内部先形成这个物理地址;

  • 不同的CPU可以有不同的形成物理地址的方式。

2.5 16位结构的CPU

在8086CPU之前的CPU都是8位机(相当于8086是分割线);8086CPU是16位结构的CPU(16位机)

概括地讲,16位结构(16位机、字长为16位)概述了一个CPU几个方面的结构特性

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

8086是16位结构的CPU,也就是说,在8086内部,能够一次性处理、传输、暂时存储的信息的最大长度是16位的。内存单元的地址在送上地址总线之前,必须在CPU中处理、传输、暂时存放。对于16位CPU,能一次性处理、传输、暂时存储16位的地址。

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

8086CPU有20位地址总线,可以传送20位地址,但它又是16位结构,在内部一次性处理、传输、暂时存储的地址是16位,从CPU内部结构来看,如果将地址从内部简单地发出,它只能送出16位的地址,寻址能力只有64KB

8086CPU内部使用地址加法器将两个16位地址合成一个20位物理地址
在这里插入图片描述

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

地址加法器采用物理地址=段地址×16+偏移地址方法合成20位的物理地址

例如8086CPU要访问地址为123C8H的内存单元,其工作过程:

在这里插入图片描述

段地址×16通俗说就是向左移四位(二进制位),十六进制就是移一位

  • 一个数据的十六进制形式移一位等同于乘以16,十进制左移一位就是乘以10,···一个X进制的数据向左移一位,相当于乘以X,向左移几位,就是乘以X的几次方

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

“段地址×16+偏移地址=物理地址”的本质含义:CPU在访问内存时,用一个基础地址(段地址×16)一个相对基础地址的偏移地址相加,给出内存单元的物理地址

更一般的说,8086CPU的这种寻址功能是“基础地址+偏移地址=物理地址寻址模式的一种具体实现方案。

举例说明基础地址+偏移地址=物理地址思想

在这里插入图片描述

①从学校去图书馆的路:

(1)从学校走2826米到图书馆,2826米可看做图书馆的物理地址

(2)从学校走2000米到体育馆,从体育馆走826米到图书馆,第一个距离2000米是相对学校的基础地址,826米是相对基础地址的偏移地址

②通过纸张相互通信,图书馆的地址只能写在纸上,现在仅有两张可以容纳三位数据的纸条。
在这里插入图片描述
第一张纸上写200(段地址),第二张纸826(偏移地址)。通过公式做运算:200×10+826=2826(物理地址)

8086CPU就是这样一个只能提供两张3位数据纸张的CPU

2.8段的概念

内存中并没有分段,段的存在是人为根据需求进行划分的,便于执行操作。在编程时可以根据需要,将若干地址连续的内存单元看做一个段,用段地址×16定位段的起始地址(基础地址),用偏移地址定位段中的内存单元。

  • 段地址×16必然是16的倍数
  • 偏移地址为16位,16位地址的寻址能力为64KB,所以一个段的长度最大为64KB

(1) CPU可用不同的段地址和偏移地址形成同一个物理地址

eg:

物理地址段地址偏移地址
21F60H2000H1F60H
2100H0F60H

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

偏移地址为16位,变化范围为0~FFFFH,仅用偏移地址来寻址最多可寻64KB个内存单元

必如给定段地址1000H,用偏移地址寻址,CPU的寻址范围为:10000H~1FFFFH。

检测点2.2

(1)给定段地址0001H,仅通过偏移地址寻址,CPU的寻址范围为0010H1000FH

SA*10H+EA=物理地址

SA*10H+(0H~FFFFH)=物理地址

l:0010H+0H=0010H

h:0010H+FFFFH=1000FH

(2)有一段数据存放在内存20000H单元中,现给定段地址为SA,若想用偏移地址寻到此单元。则SA应满足的条件是:最小为1001H最大为20000H

SA*10H+EA=物理地址=20000H

EA:(0H~FFFFH)

SAh=(20000H-0)/10H=2000H

SAl=(20000H-FFFFH)/10H=1000H 验证:1000H*10+FFFFH=1FFFFH<20000H

所以SAl=1001H

2.9 段寄存器

**段寄存器:提供段地址的部件,段地址在段寄存器中存放。8086CPU中由4个寄存器:CS、DS、SS、ES。**8086CPU访问内存时由这四个寄存器提供内存单元的段地址

2.10 CS和IP

CS和IP是8086CPU中两个最关键的寄存器,指示COU当前要读取指令的地址。

CS是代码段寄存器;IP是指令指针寄存器

在8086机中,任意时刻,CPU将CS:IP指向的内容当做指令执行
在这里插入图片描述

(1)CPU当前状态:CS:2000H IP:0000H

(2)内存20000H~20009H单元存放可执行的机器码

(3)机器码对应指令:

地址:20000H~20002H 内容:B8 23 01 长度:3Byte 对应汇编指令 mov ax,0123H

地址:20003H~20005H 内容:BB 03 00 长度:3Byte 对应汇编指令 mov bx,0003H

地址:20006H~20007H 内容:89 D8 长度:2Byte 对应汇编指令 mov ax,bx

地址:20008H~20009H 内容:01 D8 长度:2Byte 对应汇编指令 add ax,bx

指令执行过程:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结合上图:三个步骤进行循环

  1. 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓存器;

  2. IP=IP+所读取指令的长度,从而指向吓一跳指令;

  3. 执行指令,重复步骤1,2.

CPU根据什么将内存中的信息看作指令?

CPU将CS:IP指向的内存单元中的内容看做指令。因为在任意时刻,CPU都将CS、IP中的内容当做指令的段地址和偏移地址。如果说,内存中的一段地信息曾被CPU执行过,那么,他所在的内存单元必然被CS:IP指向过。

2.11 修改CS、IP指令

在CPU中,程序员能用指令读写的部件只有寄存器。通过改变寄存器中的内容实现对CPU的控制。

通过改变CS、IP中的内容来控制CPU执行目标指令

mov指令被称为传送指令 ,eg:mov bx,123将bx的值设为123;CPU中大部分寄存器的值,都可用mov命令改变,但不能改变CS、IP值

转移指令 :能够改变CS、IP的内容的指令,jmp是其中最简单的指令

“jum 段地址:偏移地址”功能:将指令中给出的段地址修改CS,偏移地址修改IP

eg:jmp 2AE3:3 执行后:CS=2AE3H,IP=0003H,CPU将从2AE33H处读取指令

jmp 3:0B16 执行后:CS=0003H,IP=0B16H,CPU将从0B46H处读取指令

仅修改IP内容:jmp 某一合法寄存器 功能:用寄存器中的值修改IP,jmp ax==mov IP,ax(不真实存在,便于理解产生)

eg:jmp ax,指令执行前:ax=1000H,CS=2000H,IP=0003H

​ 指令执行后:ax=1000H,CS=2000H,IP=1000H

jmp bx,指令执行前:bx=0B16H,CS=2000H,IP=0003H

​ 指令执行后:bx=0B16H,CS=2000H,IP=0B16H

问题2.3

内存中存放的机器码和对应的汇编指令情况如图,设CPU初始状态:CS=2000H,IP=0000H,请写出指令执行序列。在这里插入图片描述

(1)CS=2000H,IP=0000H,CPU从内存中20000H处读数据,读入指令:B8 22 66(mov ax,6622H) ax=6622H

(2)CS=2000H,IP=0003H CPU从内存中20003H处读数据,读入指令:EA 03 00 00 10(jmp 1000:3) 执行后CS=1000H,IP=0003H

(3)CS=1000H,IP=0003H,CPU从内存中10003H处读数据,读入指令:B8 00 00(mov ax,0000H) ax=0000H

(4)CS=1000H,IP=0006H,CPU从内存中10006H处读数据,读入指令:8B D8(mov bx,ax) bx=ax=0000H

(5)CS=1000H,IP=0008H,CPU从内存中10008H处读数据,读入指令:FF E3(jmp bx) 执行后 IP=0000H

(6)CS=1000H.IP=0000H,CPU从内存中10000处读取地址,读入指令:B8 23 01(mov ax,0123H) IP=IP+3=0003H…

执行序列

(1)mov ax,6622H

(2)jmp 1000:3

(3)mov ax,0000

(4)mov bx,ax

(5)jmp bx

(6)mov ax,0123H

(7)回到(3)…

2.12代码段

eg:mov ax,0000 (B8 00 00)

add ax,0123H (05 23 01)

mov bx,ax (8B D8)

jmp bx (FF E3)

这段长度为10个字节的指令,存放在123B0H123B9H的一组内存单元中,就可以认为,123B0H123B9H这段内存是用来存放代码的,是一个代码段,他的段地址是123BH,长度为10字节。如果想让这段代码得到执行,课设CS=123BH,IP=0000H。(将CS:IP指向定义代码段的第一条指令的首地址)

监测点2.3

下面的三条指令后,CPU几次修改IP?都是在什么时候?最后IP中的值是多少?

mov ax,bx

sub ax,ax

jmp ax

mov ax,bx 修改1次,执行,ax=bx

sub ax,ax 修改1次 执行,ax=0

sub=subtract减 sub ax,ax ->ax=ax-ax=0/(左=左-右)

jmp ax 修改1次,执行 修改一次 IP=ax=0

所以最后CPU修改四次,IP=0

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

在这里插入图片描述在这里插入图片描述
(1)debug功能

  • R命令:查看、修改CPU寄存器的内容
  • D:查看内存中的内容
  • E:改写内存中的内容
  • U:将内存中的机器指令翻译成汇编指令
  • T:执行CS:IP指向的内存处的指令
  • A:以汇编指令的格式在内存中写入一条机器指令

(2)本次实验在DOSbox中进行在这里插入图片描述
(3)实验内容:在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
…(-t 运行下去)
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2^8=256 256D=100H

在这里插入图片描述
在这里插入图片描述
-t…
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
不能修改,ROM(read-only memory)是只读存储器
在这里插入图片描述
在这里插入图片描述

第三章 寄存器(内存访问)

3.1 内存中字的存储

  • 字单元:存放一个字形数据(16位)的内存单元,由两个地址连续的内存单元组成。高地址内存单元中存放字形数据的高位字节,低地址内存单元中存放字形数据的低位字节。

  • 将起始地址为N的字单元简称为N地址字单元。eg:一个字单元由2,3两个内存单元组成,则可以说这是2地址字单元
    在这里插入图片描述

问题3.1

对于图3.1:

(1)0地址单元中存放的字节型数据是多少?

20H

(2)0地址字单元中存放的字形数据是多少?

4E20H

(3)2地址单元中存放的字节型数据是多少?

12H

(4)2地址字单元中存放的字形数据是多少?

0012H

(5)1地址字单元中存放的字形数据是多少?

由1号单元和2号单元组成,2号高8位,1号低8位

124EH 大小:4686

3.2 DS和[address]

DS寄存器:段寄存器.通常用来存放要访问数据的段地址

比如读取10000H单元的内容:

mov bx,1000H 将段地址放入通用寄存器bx中

mov ds,bx 令段寄存器ds=bx

8080CPU不支持直接将数据送入段寄存器;硬件设计问题导致

mov al,[0] 将内存单元的偏移地址0传送

mov命令:

  • 将数据直接送入寄存器;eg mov ax,1000H
  • 将一个寄存器内容送入另一个寄存器; eg:mov ax,bx
  • 将一个内存单元中的内容送入一个寄存器中;eg:mov al,[0] 格式:mov 寄存器名,内存单元地址

“[···]”表示一个内存单元,“[···]”中的0表示内存单元的偏移地址

段地址+偏移地址->内存地址

内存单元的段地址在哪里找呢?

  • 指令执行时,8086CPU自动取ds中的数据为内存地址中的段地址

问题3.2

写几条指令,将al中的数据送入内存单元10000H中

10000H(1000:0)

与文中示例相反 mov [0],al

所以流程:

mov bx,1000H

mov ds,bx

mov [0],al

3.3字的传送

8086CPU是16位结构,有16根数据线,所以可以一次性传送16位数据,一个字。

mov bx,1000H

mov ds,bx

mov ax,[0] 将1000:0处的字形数据送入ax(16位)中

mov [0],cx cx中16位数据送到1000:0处

问题3.3

内存中情况如图所示,写出下面的指令执行后寄存器中ax,bx,cx中的值
在这里插入图片描述

mov ax,1000H ax=1000H

mov ds,ax ds=1000H

mov ax,[0] ax=1123H 1000:0处的两个单元的 数据放入ax

mov bx,[2] bx=6622H

mov cx,[1] cx=2211H

add bx,[1] bx=bx+2211H=8833H

add cx,[2] cx=cx+6622H=8833H

问题3.4

在这里插入图片描述

11316=2C34H

mov ax 11316 ax=2C34H 10000H 34; 10001H 2C

mov [0],ax 1000:0 34;1000:1 2C

mov bx,[0] bx=2C34H

sub bx,[2] bx=bx-1122H=1b12H

mov [2],bx 1000:2 12; 1000:3 1B

在这里插入图片描述

3.4 mov、add、sub指令

已知mov命令:

mov 寄存器,数据 eg:mov ax,8

mov 寄存器,寄存器 eg:mov ax,bx

mov 寄存器,内存单元 eg:mov ax,[0]

mov 内存单元,寄存器 eg:mov [0],ax

mov 段寄存器,寄存器 eg:mov ds,ax

推倒测试成功mov命令:

mov 寄存器,段寄存器

eg:mov ax,ds在这里插入图片描述

mov 内存单元,段寄存器

eg:mov ax,1000

mov ds,ax

mov [0],ds

mov 段寄存器,内存单元

eg:mov ax,1000

mov ds,ax

mov ds,[0]

add和sub指令同mov一样,都有两个操作对象

它们不能对段寄存器进行操作;eg:add ds,ax 非法
在这里插入图片描述

在mov add sub jmp四个指令中,只有jmp是具有一个操作对象的指令

3.5数据段

段的含义参照2.8节

可认为123B0H~123B9H这段内存是一个数据段,段地址为123B,长度为10个字节。

如何访问数据段中的数据呢?

在具体操作的时候,用ds存放数据段的段地址,再根据需要,用相关指令访问数据段中的具体单元

eg:将123B0H~123B9H的内存单元定义为数据段,累加数据段中的前3个单元中的数据

mov ax,123B

mov ds,ax 数据段段地址123BH

mov al,0 用al存放累加结果

add al,[0]

add al,[1]

add al,[2]

问题3.5

在这里插入图片描述

add ax,[0] 将[0],[1] (各8位)中的内容加入ax(16位)中

add ax,[2] 将[2],[3]中的内容加入ax中

add ax,[4] 将[4],[5]中的内容加入ax中

监测点3.1

在这里插入图片描述
在这里插入图片描述

mov ax,1 ax=1

mov ds,ax ds=ax=1H

mov ax,[0000] 内存地址=段地址*10H+偏移地址=10H ax=2662H

mov bx,[0001] bx=E626H

mov ax,bx ax=bx=E626H在这里插入图片描述
mov ax,[0000] ax=2662H

mov bx,[0001] bx=D6E6H

add ax,bx ax=FD48H

add ax,[0004] ax=2C14H

mov ax,0 ax=0H在这里插入图片描述
mov al,[0002] ax=00E6H

mov bx,0 bx=0H

mov bl,[000C] bx=0026H

add al,bl ax=000CH
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

CS=2000,IP=0 指向内存地址:2000H

  1. mov ax,6622H ax=6622H CS=2000H,IP=0003H

  2. jmp 0ff0:0100 跳转指令 CS=2000,IP=0008H

    ​ 指令执行后CS=0FF0H,IP=0100H 内存地址:10000H

  3. mov ax,2000 ax=2000H CS=0FF0H,IP=0103H

  4. mov ds,ax ds=ax=2000H CS=0FF0H,IP=0105H

  5. mov ax,[0008] 此时段地址ds=2000H 偏移地址0008,指向20008位置 ax=C389H CS=0FF0,IP=0108

  6. mov ax,[0002] 指向内存地址20002H ax=EA66H

    ​ CS=0FF0H,IP=010BH

在这里插入图片描述在这里插入图片描述

3.6栈

栈是一种具有特殊的访问方式的存储空间

特点:先进后出,后进先出 (LIFO Last In First Out) 参照数据结构

栈的两个基本操作:出栈和入栈

3.7CPU提供的栈机制

8086CPU提供入栈和出栈指令(push入栈 pop出栈),出入栈操作都是以字为单位进行

push ax 将寄存器ax中的数据送入栈中

pop bx 将从栈顶取出数据放入bx

在这里插入图片描述

通过段寄存器SS和寄存器SP存放栈顶的地址,栈顶的段地址存放在段寄存器SS中,偏移地址存放在SP中。任意时刻,SS:SP指向栈顶元素
在这里插入图片描述
pop 出栈

(1)将SS:SP指向的内存单元处的数据送入ax

(2)SP=SP+2,箭头向下移两个字节,SS:SP指向当前栈顶下面的单元,成为新的栈顶在这里插入图片描述

问题3.6

如果将10000H~1000FH这段空间当做栈,初始状态栈是空的,此时SS=1000H,SP=?

栈自下向上存放数据

栈空,SS:SP指向栈空间最高地址单元的下一个单元

解析:栈空间大小:16个字节,栈底SS:SP=1000:000E

当栈中只有一个元素时,SS:SP指向1000:000E,最后一个元素出栈,出栈后,SP=SP+2=000EH+2H=0010H

所以SP=0010H在这里插入图片描述

3.8栈顶超界的问题

栈顶超界是极其危险的,可能会造成一连串的错误;

CPU不保证我们对栈的操作不会超界,8086CPU只知道栈顶在哪,但不知道栈有多大,即不知道自己指向的栈顶是否已超出栈的范围;8086CPU的工作机制:只考虑当前情况,当前的栈顶在何处,当前要执行的指令是哪一条。

在编程时,自行操心栈顶超界的问题(包括出栈和入栈)

push入栈超界:在这里插入图片描述

pop出栈超界:在这里插入图片描述

3.9 push 、pop指令

push、pop指令格式:

寄存器

  • push 寄存器 ;将一个寄存器中的数据入栈
  • pop 寄存器 ;将出栈的数据放入一个寄存器中

段寄存器:

  • push 段寄存器 ;将一个段寄存器中的数据入栈
  • pop 段寄存器 ;将出栈的数据放入一个段寄存器中

内存单元之间:

  • push 内存单元 ;将一个内存字单元处的字入栈(栈操作都是以字为单元)
  • pop 内存单元 ;用一个内存子单元接收出战的数据

eg:

mov ax,1000H

mov ds,ax 确定段地址

push [0]; 将1000:0处的数据放入栈中

pop [2]; 将出栈的数据放入1000:2处

指令执行时,CPU要知道内存单元的地址,可以在push,pop指令中只给出内存单元的偏移地址,段地址在ds中得到。
push指令执行步骤:

  1. SP=SP-2;
  2. 向SS:SP指向的字单元放入数据

pop指令执行步骤:

  1. 从SS:SP指向的字单元中读数据;
  2. SP=SP+2

问题3.7

编程,将10000H~1000FH这段空间当做栈,初始状态是空,将AX,BX,DS中的数据入栈。

指定栈顶位置

mov ax,1000H

mov ss,ax

mov sp,0010H 栈此时为空,sp=sp+2=000FH+2=0010H

将AX,BX,DS中的数据入栈

push ax

push bx

push ds
在这里插入图片描述

问题3.8

编程:

(1)将10000H~1000FH这段空间当做栈,初始状态栈是空的;

(2)设置AX=001AH,BX=001BH;

(3)将AX,BX中的数据入栈;

(4)然后将AX,BX清零;

(5)从栈中回复AX,BX原来的内容。

在这里插入图片描述
ax先进,bx先出

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

问题3.9

编程:

(1)将10000H~1000FH这段空间当做栈,初始状态栈是空的;

(2)设置AX=001AH,BX=001BH;

(3)利用栈,交换AX和BX中的数据。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

问题3.10

如果要在10000H处写入字形数据2266H,可以用以下代码完成:

mov ax,1000H

mov ds,ax

mov ax,2266H

mov [0],ax

补全下面的代码,使它能够完成相同的功能:在10000H处写入字形数据2266H。

要求:不能使用“mov 内存单元,寄存器”这类指令

使用push指令代替mov [0],ax

mov ax,1000

mov ss,ax

mov sp,0002

mov ax,2266

push ax

mov与pop,push指令不同;CPU执行mov指令只需一步操作,就是传送;执行push,pop指令需两步: push:先改变SP,后向SS:SP处传送(先说再给); pop:先读取SS:SP处的数据,后改变SP(先拿再说)

push,pop等栈操作指令,修改的只是SP,即栈顶的变化范围:0~FFFFH

3.10栈段

将一组地址连续、起始地址为16的倍数的内存单元当做栈空间来用,从而定义了一个栈段

如何使用栈段?

  • 将SS:SP指向我们定义的栈段即可

问题3.11

如果将10000H~1FFFFH这段空间当做栈段,初始状态栈是空的,此时,SS=1000H,SP=?

栈中只有一个元素是时SS:SP=1000:FFFE

栈空时SP=SP+2=0H

所以SP=0

问题3.12

一个栈段最大可以设为多少?为什么?

栈段范围大小由SP决定

SP:0~FFFFH

一个栈段容量最大为64KB

段的综述

我们可以称放数据的段为数据段;放代码的段为代码段;将一个当栈的段成为栈段

数据段:段地址在DS中,mov,add,sub等常用指令

代码段:段地址在CS中,偏移地址在IP中,mov,add,sub等常用指令

栈段:段地址在SS中,偏移地址在SP中,push,pop等常见操作指令

监测点3.2

在这里插入图片描述

mov ax,1000

mov ds,ax

mov ax,2000 //设置栈

mov ss,ax

mov sp,0010 //从栈底开始

push [0] //push ds:[0] 10000处的0123放到栈中

push [2]

push [4]

push [6]

push [8]

push [A]

push [C]

push [E]

(2)补全下面的程序,使其可以将10000H1000FH中的8个字,逆序复制到200002000F中。

mov ax,2000

mov ds,ax

mov ax,1000 //设置栈

mov ss,ax

mov sp,0

mov sp,

pop [E] //pop ds:[E] 10000H的0123放到2000E处

pop [C]

pop [A]

pop [8]

pop [6]

pop [4]

pop [2]

pop [0]

实验二 用机器指令和汇编指令编程


(一)D命令:

d 段地址:偏移地址 //实验一中段地址和偏移地址直接给出

d 段寄存器:偏移地址

CPU访问内存单元时从段寄存器中获得内存单元的段地址

debug在处理D命令的程序段中,必须有将段地址送入段寄存器的代码

段寄存器有4个:CS,SS,DS,ES

将段地址放入哪个段寄存器呢?

  1. CS:IP必须指向debug处理D命令的代码;

  2. SS:IP指向栈顶;

所以CS,SS都不行

那么只剩DS和ES。

我们知道,访问内存的指令如:mov ax,[0] 是默认段地址在ds,所以debug在处理“d 段地址:偏移地址” 这种D命令时,将段地址送入ds中比较方便

d 段寄存器:偏移地址示例:
在这里插入图片描述
(二)在E、A、U命令中使用段寄存器

方法同d命令,示例:在这里插入图片描述

实验任务

在这里插入图片描述

执行1:
在这里插入图片描述
执行二:
在这里插入图片描述在这里插入图片描述
执行三:push ax
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

mov ax,[0] ax=C0EAH

add ax,[2] ax=C0EFH

mov bx,[4] bx=30F0H

add bx,[6] bx=6021H

push ax sp:00FE 修改的内存单元地址是:2200:00FE 内容:C0FCH

push bx sp:00FC 修改的内存单元地址是:2200:00FC 内容:6021H

pop ax sp:00FE ax=6021H

pop bx sp:0100 bx=C0FCH

push [4] sp:00FE 修改的内存单元地址是:2200:00FE 内容:30F0H

push [6] sp:00FC 修改的内存单元地址是:2200:00FC 内容:2F31H

2.仔细观察图中实验,然后分析,为什么2000:0~2000:f中的内容会发生改变在这里插入图片描述

每执行一条t指令,就回将寄存器保存到栈中,栈临时保存数据(不是很理解)

第四章 第一个程序

4.1 一个源程序从写出到执行的过程

在这里插入图片描述

第一步:编写汇编源程序 -> 产生一个存储源程序的文本文件

第二步:对源程序进行编译连接 ->产生一个可在操作系统运行的可执行文件

先用汇编语言编译程序对源程序文件中的源程序进行编译,产生目标文件;

再用连接程序对目标文件进行连接,生成可在操作系统中直接运行的可执行文件

可执行文件(.exe)包括:

  • 程序(从源程序中的汇编指令翻译过来的机器码)和数据(源程序中定义的数据)
  • 相关的描述信息(比如,程序有多大,要占用多少内存…)

第三步:执行可执行文件中的程序

4.2源程序

在这里插入图片描述

1.伪指令

汇编语言源程序中包括两种指令,汇编指令和伪指令;汇编指令是有对应的机器码的指令,可被编译为机器指令,最终由CPU执行;伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作

程序4.1中

(1) XXX segment

.

.

.

XXX ends

segment和ends是一对成对使用的伪指令,写可被编译的汇编程序时必用的一对伪指令;segment和ends的功能是定义一个段,segment表示一个段的开始,ends表明一个段的结束,XXX是定义的段名

段名 segment

​ …

段名 ends

eg:程序4.1中的 codesg segment 段名是codesg

​ codesg ends

一个汇编程序由多个段组成,这些段被用来存放代码、数据或当做栈空间来使用

(2)end

end是一个汇编程序的结束标记,是整个程序的结束

(3)assume

假设;它假设某一段寄存器和程序中的某一个用segment…ends定义的段(/有特定用途的段)相关联;

程序4.1中 assume cs:codesg 就是将CPU中的段寄存器cs与段codesg联系起来

2.源程序中的“程序”

这里的“程序”值得是源程序中最终由计算机执行、处理的指令或数据

以后将源程序文件中所有内容成为源程序源程序中最终由计算机执行、处理的指令或数据成为程序
在这里插入图片描述

3.标号

例如 “codesg”,一个标号代指了一个地址

codesg在segment前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址

4.程序的结构

  1. 定义一个段,名称为abc abc segment…abc ends
  2. 在断种写入汇编指令, mov ,add…
  3. 指出程序在何处结束 end
  4. abc被当做代码段来用,将abc和cs联系起来 assume cs:abc

程序4.2

assume cs:abc

abc segment

​ mov ax,2

​ add ax,ax

​ add ax,ax

abc ends

end

5.程序返回

一个程序P2向运行,必须有一个正在运行的程序P1将其加载到内存中,将CPU的控制权交给P2,P2才能运行,P2开始运行,P1暂停,P2结束后,将CPU的控制权交还给P1,P1继续运行。

一个程序结束后,将CPU的控制权交还给使他得以运行的程序,这个过程称为:程序返回。通过在程序的末尾添加返回的程序段进行返回

mov ax,4c00H

int 21H

程序4.1中

mov ax,4c00H

int 21H

实现程序返回

6.语法错误和逻辑错误

**当程序没有返回时,编译是不报错的,**对编译器来说程序4.2是正确的程序。

程序在编译时报错是语法错误

运行时发生的错误是逻辑错误

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值