《汇编语言》 学习笔记

《汇编语言》 学习笔记

第一章 基础知识

1.1 机器语言

每一种微处理器,由于硬件设计和内部结构的不同,就需要不同的点评脉冲来控制,使他工作。所以每一种微处理器都有自己的机器指令级,也就是机器语言。

1.2 汇编语言的产生

image-20220220002459635

此后,程序员使用汇编指令编写源程序,这时候就需要使用编译器,将汇编指令转成机器指令的编译程序。

image-20220220002729801

1.3 汇编语言的组成

汇编语言发展至今,有以下三类指令组成

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

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

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

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

1.4 存储器

存储器中存储CPU需要的指令与数据,也就是平时所说的内存。

1.5 指令与数据

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

CPU在工作时才会赋予不同意义,使其发挥不同的作用。

image-20220220005158751

1.6 存储单元

存储器被划分成若干个存储单元每个存储单元从0开始顺序编号,例如一个存储器有128个存储单元,编号从0~127,如下图所示

image-20220220005543172

这些编号可以看作存储单元在存储器中的地址

计算机最小的信息单元为bit(音译为比特),也就是一个二进制位

8个bit组成一个Byte,也就是一个字节

微型机存储器:每个存储单元可以存储一个Byte即8个二进制位,一个存储器有128个存储单元,它可以存储128个Byte,即1024个二进制位。微机存储器的容量是以字节为最小单位

大容量存储器:一般用以下单位计量容量(以下B代表Byte)

  • 1KB = 1024B
  • 1MB = 1024KB
  • 1GB = 1024MB
  • 1TB = 1024GB

1.7 CPU对存储器的读写

CPU要从内存中读数据,首先要指定存储单元的地址。

在微机中,不只有存储器这一种期间,所以CPU在读写数据的时候还要指明,它要对那个器件进行操作,进行那种操作,从中读取数据,还是向里面写入数据。

可见,CPU要进行数据读写,必须和外部器件,进行下面3类的信息交互

  • 地址信息:存储单元的地址
  • 控制信息:器件的选择,读或写的命令
  • 数据信息:读或写的数据

电子计算机能处理、传输的信号都是电信号,要是用导线传送。在计算机中专门有连接CPU和其他芯片的导线,通称为总线

总线根据传送信息的不同,从逻辑上分为3类,地址总线、控制总线和数据总线。

CPU从3号单元读取数据的过程如下:

image-20220220011811726

  1. CPU通过地址线将地址信息3发出
  2. CPU通过控制线发出内存读命令,选中存储器芯片,并通知它,将要从中读取数据
  3. 存储器将3号单元中的数据8通过数据线送入CPU

要让一个计算机或者危机处理器工作,影响他输入能够驱动他进行工作的电平信息(机器码)

对于8086CPU,下面的代码能实现从3号单元读取数据

机器码:10100001 00000011 00000000

汇编指令:MOV AX,[3]

含义:传送3号单元的内容入寄存器AX

1.8 地址总线

地址总线上能够传多少个不同信息,CPU就能对多少个存储单元进行寻址。

地址总线的宽度决定了CPU的寻址能力。

在电子计算机中,一根导线可以传送的稳定状态只有两种,高电平或是低电平,用二进制表示就是1或者0,10跟导线可以传送10位二进制数据,10位二进制数据可以表示2的10次方个不同的数据,最小为0最大为1023。

一个CPU有N跟地址线,则可以说这个CPU的地址总线宽度为N,这样的CPU最多可以寻找2的N次方个内存地址(Byte)

下图展示了一个具有10跟地址线的CPU向内存发出地址信息11时10跟地址总线上传送的二进制信息

image-20220220013429547

访问地址为12时,地址总线上穿得内容就是12的二进制数据即000000 1100

访问地址13时,地址总线数据为000000 1101

访问地址14时,地址总线数据为000000 1110

1.9 数据总线

CPU与内存或其他器件之间的数据传送是通过数据总线进行的。

数据总线的宽度决定了CPU与外界的数据传送速度。

8跟数据总线一次可以传一个8位二进制数据(即一个字节),16根数据总线一次可传送两个字节。

image-20220220014252766

image-20220220014307262

1.10 控制总线

CPU对外部器件的控制是通过控制总线进行的,控制总线是个总称,是一些不同的控制线的集合有多少跟控制总线,就意味着CPU提供了对外器件的多少种控制

所以,控制总线的宽度决定了CPU对外部器件的控制能力。

前面所讲的内存读或写是由几根控制总线综合发出的,其中一个称为“读信号输出”的控制线负责由CPU向外传送读信号,CPU向该控制线上输出低电压表示将要读取数据;有一个称为“写信号输出”的控制总线负责传送写信号。

1.11 内存地址空间(概述)

系统中的所有存储器中的存储单元都处于一个统一的逻辑存储器中,它的容量受CPU寻址能力的限制,这个逻辑存储器即使我们所说的内存地址空间。

1.12 主板

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

1.13 接口卡

CPU对外部设备无法直接控制,如显示器、音响、打印机等。直接控制这些设备进行工作的是插在拓展插槽上的接口卡。拓展插槽通过总线和CPU相连,所以接口也通过总线同CPU相连。

总的来说,CPU通过总线向接口卡发送命令,接口卡根据CPU的命令控制外设进行工作。

1.14 各类存储器芯片

这些存储器芯片从物理连接上看是独立的、不同的器件。从读写属性上看分为两类:

  • 随机存储器(RAM):可读可写,关机后存储内容丢失
  • 只读存储器(ROM):只能读取不能写入,关机后其中内容不丢失

从功能和连接上看可分为三类:

  • 随机存储器

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

  • 装有BIOS(Basic Input/output System,基本输入/输出系统)的ROM

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

  • 接口卡上的RAM

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

    image-20220220161533317

1.15 内存地址空间

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

image-20220228143638841

CPU向显存地址空间中,然后会被显卡输出到显示器上

CPU向显卡BIOS ROM写入数据,写入的单元内容不会改变

内存地址空间的大小受CPU地址总线宽度的限制

​ 8086CPU地址总线宽度为20,可以传送2^20个不同的地址信息(大小从0至2^20-1),则8086PC的内存地址空间的大小为1MB。同理80386CPU的总线宽度为32,内存空间的最大为4MB

我们基于计算机硬件系统编程的时候,必须知道这个系统的内存中的内存地址空间分配情况。当我们想在某类存储器中读写数据的时候,必须知道它的第一个单元的地址和最后一个单元的地址,才能保证读写操作是在预期的存储器中进行。

不同的内存地址空间分配情况不同,下图是8086PC机内存储地址空间分配的进本情况

image-20220228201433581

向地址C0000~FFFF的内存单元写入数据的操作是无效的,因此这等于改写制度存储器中的内容。

image-20220228201641591

第二章 寄存器

在CPU中

  • 运算器进行信息处理

  • 寄存器进行信息存储

  • 控制器控制各种器件进行工作

  • 内部总线连接各种器件,在他们之间进行数据的传送

对于一个汇编程序员来说,CPU中的主要部件是寄存器。寄存器是CPU中程序可以用指令读写的部件。程序员通过各种寄存器中的内容来实现对CPU的控制。

不同的CPU寄存器的个数、结构是不同的

2.1 通用寄存器

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

AX、BX、CX、DX这4个寄存器通常用来存放一般性的数据,被称为通用寄存器。

以AX为例,寄存器的逻辑结构如图所示

image-20220228202422766

一个16位寄存器所能存储的数据的最大值约为两字节

8086CPU上一代CPU中的存储器都是8位的,为了保证兼容性,需要使得AX、BX、CX、DX这四个寄存器都可分为两个独立使用的8位寄存器使用。见下图

image-20220228203013441

image-20220228203649552

一个16位寄存器可以存储一个16位的数据,数据在寄存器中的存放情况如下图所示

image-20220228203340810

2.2 字在寄存器中的存储

8086CPU可以一次处理一下两种尺寸的数据

  • 字节:记为BYTE,一个字节由8个bit组成,可以存放在8位寄存器中
  • 字:记为word,一个字由两个字节组成,这两个字节分别成为这个字的高位字节和低位字节。

一个字可以存放在一个16位寄存器中,这个字的高位字节和低位字节自然存在这个寄存器的高8位寄存器和低8位寄存器中

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

汇编指令不区分大小写

程序段中的指令 指令执行后AX中的数据 指令执行后BX中的数据
MOV AX,4E20H 4E20H 0000H
ADD AX,1406H 6226H 0000H
MOV BX,2000H 6226H 2000H
ADD AX,BX 8226H 2000H
MOV BX,AX 8226H 8226H
ADD AX,BX 044CH 8226H

由于ax寄存器是16位寄存器只能存放4位十六进制的数据,但是在执行add ax,bx指令后ax1033C,超出了ax寄存器的上限,所以1044C中的最高位1不能存放在ax寄存器中,最终ax寄存器中的数据为044CH

再看一段程序的执行情况

程序段中的指令 AX BX
MOV AX,001AH 001AH 0000H
MOV BX,0026H 001AH 0026H
ADD AL,BL 0040H 0026H
ADD AH,BL 2640H 0026H
ADD BH,AL 2640H 4026H
MOV AH,0 0040H 4026H
ADD AL,85H 00C5H 4026H
ADD AL,93H 0058H 4026H

程序的最后一条指令mov al,93h在执行前,al中的值为C5H,相加后为158H,但是由于al为8位寄存器,只能存放两位十六进制数据,所以最高位1丢失,ax中的值位0058h

此时,al是作为一个独立的8位寄存器使用,和ah没有关系

若执行的是add ax,93h低8位的进位会存储在ah中,CPU再执行指令时,只认为有1个16位寄存器ax进行的是16位计算,执行完这条指令后,ax中的值变为0158h使用的寄存器是16位寄存器ax相当于00C5H加上0093H

错误指令:

​ mov ax,bx ;在8位寄存器和16位寄存器之间传送数据

​ mov bh,ax ;在16位寄存器和8位寄存器之间传送数据

​ mov al,20000 ;8位寄存器最大可存放值为255的数据

​ add al,100h ;将一个高于8位的数据加到一个8位寄存器中

检测

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

mov ax,2
add ax,ax
add ax,ax
add ax,ax

2.4 物理地址

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

CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。在CPU向地址总线上发出物理地址之前,必须要先在内部形成这个物理地址。

2.5 16位结构的CPU

概括的说,16位结构(16位机,字长为16位)描述了一个CPU具有下面几方面的结构特性。

  • 运算器一次最多可以处理16位的数据

  • 寄存器最大的宽度位16位

  • 寄存器和运算器之间的通路为16位

在十六位结构的CPU内部,能过一次性处理、传输、暂时存储的信息最大长度是16位的

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

8086CPU采用一种在内部用两个16位地址合成的方法来形成一个20位的物理地址

image-20220301111723273

如图所示,当8086CPU要读写内存时:

  1. cpu中的相关部件提供两个16位地址,一个段地址,另一个时偏移地址

  2. 段地址和偏移地址通过内部总线送入一个称为地址加法器的部件

  3. 地址加法器将两个16位地址合成一个20位的物理地址

  4. 地址加法器通过内部总线将20位物理地址送入输入输出控制电路

  5. 输入输出控制电路将20位物理地址送上地址总线

  6. 20位物理地址被地址总线送到存储器

image-20220301112042771

其中,地址加法器采用物理地址=段地址*16+偏移地址的方法用段地址合成物理地址

2.7 段地址*16+偏移地址的本质含义

CPU在访问内存时,用一个基础地址(段地址*16)和一个相对于基础地址的偏移地址相加,给出内存单元的物理地址。

8086CPU中,段地址*16可看作基础地址(起始地址)

2.8 段的概念

内存并没有分段,段的含义来自于CPU

以后在编程的时候可以根据需要,将若干连续的内存单元看作一个段,用段地址*16定位段的起始地址(及地址)用偏移地址定位段中的内存单元。

有两点需要注意:段地址*16必然是16的倍数,所以一个段的起始地址也一定是16的倍数;偏移地址为16位,16位的地址寻址能力为64KB,所以一个段的长度最大为64KB。

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

如果给定一个段地址,仅通过变化偏移地址来进行寻址,最多可以定位64KB个内存单元,因为偏移地址16位,变化范围为0~FFFFH

2.9 段寄存器

段地址在8086CPU的段寄存器中存放,8086CPU有四个段寄存器,CS、DS、SS、ES。当8086CPU要访问内存时由这四个段寄存器提供内存单元的段地址

2.9 CS和IP

CS和IP时8086CPU中两个最为关键的寄存器,他们指示了CPU当前要读取地址的地址。

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

在8086PC中任意时刻,设CS中的内容为M,IP中的内容为N,8086CPU将从内存M*16+N单元开始,读取一条指令并执行

也可以这样表述,任意时刻,CPU将CS:IP指向的内容当作指令执行

image-20220301115435781

8086CPU的工作过程可以简要描述如下

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

在8086CPU加点启动或复位后(即CPU刚开始工作时),CS和IP被设置为CS=FFFFH,IP=0000H,即在刚启动时候,CPU从内存单元FFFF0H端元读取指令执行,FFFF0H单元中的指令是8086PC机开机后执行的第一条指令

CPU将CS:IP指向的内存单元中的内容看作指令,因为,在任何时候,CPU将CS、IP中的内容当作指令的段地址偏移地址,用他们合成指令的物理地址,到内存中读取指令码。

2.11 修改CS、IP的指令

mov指令不能设置CS、IP的值,需要使用jmp指令进行修改

若想修改CS、IP的内容,可以用形如"JMP 段地址:偏移地址"的指令完成,如

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

"JMP 段地址:偏移地址"的功能是:用指令中给出的段地址修改CS,偏移地址(IP)

jmp ax在含以上等同于 mov IP,ax

jmp 3:01B6含以上等同于mov CS,3 mov ax,01B6

设CPU初始状态CS=2000H,IP=0000H,请写出指令执行序列

image-20220303203536760

  1. 当CS=2000H,IP=0000H时,CPU从2000h*16+0h=20000h处读取指令,读入的指令是:B8 22 66(MOV AX,6622H),读入后IP=IP+3=0003h
  2. 指令执行后,CS=2000H(未变),IP=0003h,则CPU从内存2000h*16+0003h=20003处读取指令,读入的指令是EA 03 00 00 10(JMP 1000:0003),读入后IP=IP+5=0008H
  3. 指令执行后,CS=1000H,IP=0003H,则CPU从内存1000h*16+0003h=10003h处读取指令,读入的指令是B8 00 00(MOV AX,0000)读入后IP=IP+3=0006H
  4. ......

分析后可知指令序列为

mov ax,6622h

jmp 100:3

mov ax,0000

mov bx,ax

jmp bx

mov ax,0123h

转到第三步执行

2.12 代码段

将一段内存单元定义为一个段,将长度N(N<=64KB)的一簇代码,存在一组地址连续、起始地址是16倍数的内存单元中

例如

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

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

DEBUG基础指令

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

alt+enter 将dos窗口切换为全屏模式

R 查看、改写寄存器中的值

posted @ 2022-03-16 22:53  MuRKuo  阅读(224)  评论(0编辑  收藏  举报