《汇编语言》——王爽第三版笔记(1-3章)

汇编语言

书籍电子版 提取码: b62a
书上内容比较全,初学者多看看王爽老师的书。有不懂的再来查。
笔记是简略版,有检测点和实验的答案,还有自己的理解。

前言

在学之前,搞清楚本书的重心:

通过学习关键指令来深入理解机器工作的基本原理,培养底层编程意识和思想。

读者应具备以下知识:

  • 二进制、十六进制的知识
  • 一门高级语言基本编程基础(顺序,选择,循环)

第一章:基本知识

位、字、字长、字节

  • 位(bit,b):是计算机中最小的数据单位,一个位的值只可能是0或1
  • 字节(Byte,B):8位是一个字节
  • 字长:CPU在单位时间可以处理的最大二进制的位数。8位CPU,也就是单位时间内最大可以处理一字节。
  • 字(Word,W):计算机处理数据时,一次存取、加工、传送的数据的长度称为字。一个字通常是由多个字节构成。字长为32的CPU,一个字等于4个字节。显然,字与字长有关,可以理解为:一个字 = 字长/8。

机器语言

  1. 机器语言是机器指令的集合
  2. 机器指令展开来讲就是一台机器可以正确执行的命令。

汇编语言的产生

  1. 汇编语言的主体是汇编指令
  2. 汇编指令与机器指令的差别在于指令的表示方法上。汇编指令是机器指令便于记忆的书写格式。
  3. 汇编指令是机器指令的助记符。

汇编语言的产生

机器只认识二进制,机器语言就是一堆二进制码。所有的高级语言写的源程序最终都会变成二进制,给机器运行。

机器语言人难写又难读,所以就用另一种人比较好看的语言来做这些事情,通过编译器最终转换成机器语言。

这个转换过程叫做翻译。

寄存器:CPU中可以存储数据的器件,一个CPU中有多个寄存器。

汇编语言的组成

  1. 汇编指令(机器码的助记符,有对应的机器码)
  2. 伪指令(没有对应的机器码,由编译器执行,计算机不执行)
  3. 其它符号(由编译器识别,没有对应的机器码)

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

存储器

CPU是计算机的核心部件,它控制整个计算机的运作并时进行运算,要想让一个CPU工作,就必须向它提供指令和数据。

指令和数据在存储器中存放, 也就是平时所说的内存。计算机中的硬件一般都有固定的存储,显卡,网卡,BIOS都有。

存储单元

存储器被划分为若干个存储单元,每个存储单元从0开始编号。

微机存储器的容量是以字节为最小单位来计算的,一个存储单元就是1Byte,即8个二进制位。也就是说64KB就是10^16字节,字节单位已经是最小单位了,不能再细分了。

B=>KB=>MB=>GB=>TB

指令和数据

在计算机的内存和磁盘上,只有二进制数。这些二进制数有两种可能,要么是数据,要么是指令。

CPU对存储器的读写

  1. 存储单元的地址(地址信息)
  2. 器件的选择,读或写命令(控制信息)
  3. 读或写的数据(数据信息)

在这里插入图片描述

地址线发出操作3这个地址,控制线说是读,数据线将08读入CPU。

同理:地址线发出操作3这个地址,控制线说是写,数据线将一个数据写进3这个内存单元。

三大总线

  • 地址总线:

    • CPU是通过地址总线来指定存储单元的*(定位的是Byte,不是bit)*

      尤其要注意这里,能寻址的最小单元是字节单元,也就是说,这个单元上的二进制能表达256种可能。

    • 地址总线上能传送多少个不同的信息,CPU就可以对多少个存储单元进行寻址

    一个CPU有N根地址总线,则可以说这个CPU的地址总线的宽度为N

    其最多可以寻找2的N次方个内存单元(2^N byte)

在这里插入图片描述

  • 控制总线

    • CPU对外部器件的控制是通过控制总线来进行的。在这里控制总线是个总称,控制总线是一些不同控制线的集合
    • 有多少根控制总线,就意味着CPU提供了对外部器件的多少种控制,其宽度决定了CPU对外部器件的控制能力

    内存的读或写命令是由几根控制线综合发出的:

    • 其中有一根名为读信号输出控制线负责由CPU向外传送读信号,CPU向该控制线上输出低电平表示将要读取数据
    • 有一根名为写信号输出控制线负责由CPU由外传送写信号

    可以粗略的理解为每一条线对应一个东西,发送0、1进行读写。

  • 数据总线

    • CPU和内存或其它器件之间的数据传送是通过数据总线来进行的
    • 数据总线的宽度决定了CPU和外界的数据传送速度

    数据总线与地址总线不同了,他的一根线就表示一位。8位数据(1byte)就要8根线,而地址线找地址一根就能找两种内存单元(byte)。

在这里插入图片描述

在这里插入图片描述

注意点

地址总线寻址是从存储(内存)单元寻址的,从寻址来说,存储单元就是最小可编址单位,一般就是1Byte。一根就是1Byte。N根就是2^N个Byte。

数据总线一根就是一位。

内存编址:存储器由许多可存放一段信息的单元(位置)组成,每个单元都有一个编号,程序可以通过这个编号来访问这个单元,这个编号就是这个单元的地址。

显然地址总线就是通过这个编号来访问每一个地址单元的,而地址线一根就是两种状态,通过组合又组成了多种状态来找到这个编号。 如果有6个单元就至少需要3根线(2^3=8)。

检测: 检测点1.1

内存地址空间

一个CPU地址总线宽度为10,那么可以寻址1024个内存单元(Byte),这个1024个可寻址的单元就构成了CPU的内存地址空间。

主板

主板上有一些主要部件和一些核心器件,这些器件通过三大总线相连。CPU、存储器、外围芯片组、扩展卡槽等

接口卡

计算机系统中,所有可用程序控制其工作的设备,都要受到CPU的控制,但是CPU并不能直接控制这些设备,直接控制这些的是在扩展卡槽上的接口卡,扩展卡槽通过总线与CPU相连,所以接口卡也相连。CPU可以直接控制这些接口卡,来间接的控制这些外部设备。

CPU ——> 接口卡——>外设

各类存储器芯片

一台PC机中,装有多个存储器芯片。

物理上来看这些芯片是独立的,从读写属性上分为两类

  • RAM 可读写,掉电内容丢失
  • ROM 只读

从功能和连接上分为

  1. 随机存储器RAM

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

    1. 装在主板上RAM
    2. 插在扩展插槽上的RAM
  2. 装有BIOS(Basic Input/Output System)的ROM

    BIOS是由主板和各类接口卡厂商提供的软件系统,可以通过它利用该硬件设备进行最基本的输入与输出。

    主板有主板的BIOS

    显卡有显卡的BIOS

    如果网卡有ROM,那其中就可以存储网卡的BIOS

  3. 接口卡上的RAM

    某些接口卡需要对大批量输入、输出数据进行暂时存储,在其上装有RAM。

    典型的是显卡上的显存,显示卡随时将显存中的数据向显示器上输出,将需要的内空写入显存,就会出现在显存中。

在这里插入图片描述

内存地址空间

上面的存储器在物理上是独立的,但是下面两点是相同的

  • 都和CPU的总线相连
  • CPU对它们进行读或写的时候都通过控制线发出内存读写命令

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

在这里插入图片描述

所有物理存储器被看作一个由若干存储单元组成的逻辑存储器,每个物理存储器在这个逻辑存储器中占有一个地址段,即一段地址空间。CPU在这段地址空间中读写数据,实际上就是在对应的物理存储器中读写数据。

内存地址空间大小受CPU地址总线宽度的限制,8086CPU地址总线宽度为20,所以8086PC内存地址空间为1MB,80386地址总线为32,则PC内存地址空间为4GB。
在这里插入图片描述

第二章:寄存器

一个典型的CPU由运算符、控制器、寄存器等器件构成,这些器件靠内部总线相连。

前一章说的总线相对于CPU内部而言其实是外部总线,而内部也有一个总线,实现了CPU内部各个器件之间的联系,外部总线实现CPU和主板上其他器件的联系。

在CPU内部

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

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

这里的寄存器是在CPU中的

8086CPU

8086CPU中的所有寄存器都是16位的

通用寄存器

AX、BX、CX、DX

为了兼容上一代的8位寄存器, 这4个寄存器都可以分为两个可独立使用的8位寄存器。

以AX为例高8位AH,低8位AL。
在这里插入图片描述

在这里插入图片描述

上面表中AX最高位少了一个0

字在寄存器中的存储

8086CPU:

  • 字节:Byte,8bit
  • 字:两个字节,就是16位,分别是高位字节和低位字节

几条汇编指令

在这里插入图片描述

汇编指令和寄存器名称不区分大小写。
在这里插入图片描述
在这里插入图片描述

检测: 检测点2.1

物理地址

CPU访问内存单元时,要给出内存单元的地址,所有内存单元给同的存储空间是一个一维的线性空间,每一个内存单元在这个空间中都有唯一的地址,这个地址就是物理地址。

CPU通过地址总线送入存储器的,必须是一个内存单元的物理地址。而这个物理地址,不同的CPU有不同的形成方式。

8086CPU(16位结构的CPU)

16位的CPU(16位机,字长为16位),意味着:

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

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

8086CPU给出物理地址的方法

8086CPU有20位的地址总线,达到1MB的寻址能力,8086CPU又是16位的结构,如果从内部发出的话,也只能发出16位,8086CPU用段地址+偏移地址的方法来形成一个20位的物理地址。

在这里插入图片描述

物理地址=段地址*16 + 偏移地址

乘16也就意味着16进制数左移一位,也就是16位的2进制数变成了20 位的2进制数,再加上这个偏移地址,就形成了可以确定的20位的物理地址。

段的概念

要注意的是,内存其实没有分段,是CPU搞出来的段地址。

下面两张图:

可以认为左边的10000H-100FFH组成一个段,起始地址为10000H,段地址为1000H,大小为100FFH-10000H = 100H

可以认为右边的10000H-1007FH组成一个段,10080H-100FFH组成一个段,大小都为80H。

在这里插入图片描述

可以看出,起始地址=段地址*16,必然是16的倍数。

在8086CPU中,偏移地址是16位,最大寻址是64KB,0000H-FFFFH,想要两个段接得上,段的长度应该是64KB。

总结

在8086PC机中,存储单元的地址用两个元素来描述,段地址和偏移地址。

数据在21F60H内存单元中,一般不这么说,要说:

  • 数据在2000:1F60单元中
  • 数据在2000段中的1F60H单元

检测: 检测点2.2

段寄存器

8086CPU在访问内存时需要段地址与偏移地址,送入地址加法器合成物理地址。这里就是由寄存器提供地址,段寄存器提供段地址。

8086CPU有4个段寄存器:

  • CS(Code Segment)
  • DS(Data Segment)
  • SS(Stack Segment)
  • ES(Extra Segment)

CS和IP

IP(instruction point):指令指针寄存器

8086PC机中,CS中的内容为M,IP中的内容为N,8086将从M*16 + N的内存单元开始,读取一条指令并执行。

IP执行完当前指令后会自动移到下一条指令的位置。如果当前指令是3个字节那就加3,如果是两个字节就加2。

8086CPU工作过程:

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

在8086CPU加电启动或复位,CS = FFFFH,IP = 0000H,FFFF0H是开机后的第一条指令。

CPU将CS、IP中的内容当作指令的段地址和偏移地址

修改CS、IP

程序员可以通过改变CS、IP中的内容来控制CPU执行目标指令。

jmp 段地址:偏移地址 

用指令中给出的段地址修改CS,偏移地址修改IP

jmp 偏移地址

改变IP

CPU只认被CS:IP指向的内存单元中的内容为指令。

检测: 检测点2.3

实验1

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

第二章从CPU如何执行指令的角度讲解了8086CPU的逻辑结构、形成物理地址的方法、相关寄存器以及一些指令。

这一章从访问内存角度学习寄存器。

内存中的存储

数据和程序在内存中,都是二进制文件,能访问的地址也就是一个字节,用16进制来表示。CPU中,用16位寄存器来存储一个字,高8位存放高字节,低8位放低字节。
在这里插入图片描述

在这里插入图片描述

上图的0,1,2,3……就是能访问到的地址,用16进制来表示一个字节,比如20H,4EH等等。

由于内存单元是字节单元,则一个字就要用两个连续的内存单元来存。图中0、1两个内存单元存放数据4E20H,0是低地址单元,1是高地址单元。

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

以起始地址为N的字单元简称N地址字单元。

DS和address

CPU要读写一个内存单元时,必须先给出这个内存单元的地址,在8086PC中,内存地址由段地址和偏移地址组成。

8086CPU中有一个DS寄存器用于存放段地址(注意DS寄存器也应该是16位的,不是20位的)

mov bx, 1000H
mov ds, bx
mov al, [0]
//将1000:0中的数据读到al中

为什么不能是

mov ds 1000H

因为8086CPU不支持将数据直接送入段寄存器(设计缺陷)

传送多少的数据是由最后的通用寄存器决定的,如果是ax、bx就传16位,最大也就只能传16位,而如果是al、ah,那就传送8位。

字的传送

8086CPU是16位结构,一次传送16位数据。

mov bx, 1000H
mov ds, bx
mov ax, [0]
mov [0], cx

16进制数一个数字代表四个二制数,4个数就是16个二进制数,也就是16位。

高位在高地址,低位在低地址

mov、add、sub指令

  1. mov 指令可以对寄存器,数据,内存单元之间的随意赋值
  2. add、sub指令不可以用于段寄存器(以s结尾的寄存器segment)

数据段

可以将一组长度为N<=64KB、地址连续、起始地址为16的倍数的内存单元当作专门存储数据的内存空间。

ds中存放数据段的段地址,再自己根据需要访问段中的单元。

栈是一个存储空间,据有特殊的访问方式。先进后出,First in last out

由图形来看的话就也是一段空间,如下图,但是注意这段空间高地址在下面,低地址在上面。

在这里插入图片描述

检测: 检测点3.1

CPU提供的栈机制

ss:sp在任意时刻都指向栈顶元素,push入栈,pop出栈

在刚开始时,栈的长度是sp所决定的,ss为段地址,也就是低地址,在图上来说就是在上方,而sp始终指向栈顶,当栈为空时,栈顶应该在栈的最底部的下面。也就是最高地址的后面。按上图10000H~1000FH来说,ss=1000H,sp=10H。长度就是16byte。

栈顶越界问题

如果一直push肯定总有一天会满栈然后越界,如果一直pop,肯定总有一天会空栈然后也越界。要求编程人员自己注意。

push、pop指令

  • push
push 寄存器 将寄存器中的数据入栈
  1. sp = sp-2,先让sp指向当前栈顶前面的单元,也就是将要送入数据的单元
  2. 将寄存器中的内容送入ss:sp指向的内存单元,此时ss:sp就指向新栈顶
  • pop
pop 寄存器 将栈中的数据送入寄存器
  1. 将ss:sp指向的内存单元中的数据送入到寄存器中

  2. sp = sp+2,让sp指向当前栈顶下面的内存单元,以这个单元为新的栈顶

8086CPU是16位的CPU,所以一次操作16位二进制数据,也就是4位16进制数据。一个内存单元中的数据是一个字节,也就是8位数据,在push和pop时,一次改变两个内存单元。

栈段

栈段就是当作栈来使用的一段空间。显然sp<=64KB(ffff),所以栈段最大不超过64KB

比如 10010H~1001FH,这是一个16字节的内存单元。

检测: 检测点3.2

第1 基础知识 1.1 机器语言 1.2 汇编语言的产生 1.3 汇编语言的组成 1.4 存储器 1.5 指令和数据 1.6 存储单元 1.7 CPU对存储器的读写 1.8 地址总线 1.9 数据总线 1.10 控制总线 1.11 内存地址空间(概述) 1.12 主板 1.13 接口卡 1.14 各类存储器芯片 1.15 内存地址空间 第2 寄存器 2.1通用寄存器 2.2字在寄存器中的存储 2.3几条汇编指令 2.4物理地址 2.516位结构的CPU 2.68086CPU给出物理地址的方法 2.7“段地址×16+偏移地址=物理地址” 的本质含义 2.8段的概念 2.9段寄存器 2.10CS和IP 2.11修改CS、IP的指令 2.12代码段 实验1查看CPU和内存,用机器指令 和汇编指令编程 第3寄存器(内存访问) 3.1内存中字的存储 3.2DS和(address) 3.3字的传送 3.4mov、add、sub指令 3.5数据段 3.6栈 3.7CPU提供的栈机制 3.8栈顶超界的问题 3.9push、pop指令 3.10栈段 实验2用机器指令和汇编指令编程 第4第一个程序 4.1一个源程序从写出到执行的过程 4.2源程序 4.3编辑源程序 4.4编译 4.5连接 4.6以简化的方式进行编译和连接 4.71.exe的执行 4.8谁将可执行文件中的程序装载进入 内存并使它运行? 4.9程序执行过程的跟踪 实验3编程、编译、连接、跟踪 第5(BX)和loop指令 5.1(BX) 5.2Loop指令 5.3在Debug中跟踪用loop指令实现的 循环程序 5.4Debug和汇编编译器masm对指令的 不同处理 5.5loop和(bx)的联合应用 5.6段前缀 5.7一段安全的空间 5.8段前缀的使用 实验4(bx)和loop的使用 第6 包含多个段的程序 6.1在代码段中使用数据 6.2在代码段中使用栈 6.3将数据、代码、栈放入不同的段 实验5编写、调试具有多个段的程序 第7更灵活的定位内存地址的 方法 7.1anol和or指令 7.2关于ASCII码 7.3以字符形式给出的数据 7.4大小写转换的问题 7.5(bx+idata) 7.6用(bx+idata)的方式进行数组的 处理 7.7SI和DI 7.8(bx+si)和(bx+di) 7.9(bx+si+idata)和(bx+di+idata) 7.10不同的寻址方式的灵活应用 实验6实践课程中的程序 第8数据处理的两个基本问题 8.1bx、si、di和bp 8.2机器指令处理的数据在什么地方 8.3汇编语言中数据位置的表达 8.4寻址方式 8.5指令要处理的数据有多长 8.6寻址方式的综合应用 8.7div指令 8.8伪指令dd 8.9dup 实验7寻址方式在结构化数据访问中的 应用 第9转移指令的原理 9.1操作符offset 9.2jmp指令 9.3依据位移进行转移的jmp指令 9.4转移的目的地址在指令中的jmp 指令 9.5转移地址在寄存器中的jmp指令 9.6转移地址在内存中的jmp指令 9.7jcxz指令 9.8loop指令 9.9根据位移进行转移的意义 9.10编译器对转移位移超界的检测 实验8分析一个奇怪的程序 实验9根据材料编程 第10CALL和RET指令 10.1ret和retf 10.2call指令 10.3依据位移进行转移的call指令 10.4转移的目的地址在指令中的call 指令 10.5转移地址在寄存器中的call指令 10.6转移地址在内存中的call指令 10.7call和ret的配合使用 10.8mul指令 10.9模块化程序设计 10.10参数和结果传递的问题 10.11批量数据的传递 10.12寄存器冲突的问题 实验10编写子程序 课程设计1 第11标志寄存器 11.1ZF标志 11.2PF标志 11.3SF标志 11.4CF标志 11.5OF标志 11.6adc指令 11.7sbb指令 11.8cmp指令 11.9检测比较结果的条件转移指令 11.10DF标志和串传送指令 11.11pushf和popf 11.12标志寄存器在Debug中的表示 实验11编写子程序 第12内中断 12.1内中断的产生 12.2中断处理程序 12.3中断向量表 12.4中断过程 12.5中断处理程序和iret指令 12.6除法错误中断的处理 12.7编程处理0号中断 12.8安装 12.9do0 12.10设置中断向量 12.11单步中断 12.12响应中断的特殊情况 实验12编写0号中断的处理程序 第13int指令 13.1int指令 13.2编写供应用程序调用的 中断例程 13.3对int、iret和栈的深入理解 13.4BIOS和DOS所提供的 中断例程 13.5BIOS和DOS中断例程的 安装过程 13.6BIOS中断例程应用 13.7DOS中断例程应用 实验13编写、应用中断例程 第14端口 14.1端口的读写 14.2CMOS RAM芯片 14.3shl和shr指令 14.4CMOS RAM中存储的时间信息 实验14访问CMOS RAM 第15外中断 15.1接口芯片和端口 15.2外中断信息 15.3PC机键盘的处理过程 15.4编写int 9中断例程 15.5安装新的int 9中断例程 实验15安装新的int 9中断例程 第16直接定址表 16.1描述了单元长度的标号 16.2在其他段中使用数据标号 16_3直接定址表 16.4程序入口地址的直接定址表 实验16编写包含多个功能子程序的 中断例程 第17使用BIOS进行键盘输入 和磁盘读写 17.1int 9中断例程对键盘输入的处理 17.2使用int 16h中断例程读取 键盘缓冲区 17.3字符串的输入 17.4应用int 13h中断例程对磁盘 进行读写 实验17编写包含多个功能子程序的 中断例程 课程设计2 综合研究 研究试验1搭建一个精简的C语言 开发环境 研究试验2使用寄存器 研究试验3使用内存空间 研究试验4不用main函数编程 研究试验5函数如何接收不定数量的 参数 附注 附注1Intel系列微处理器的3种工作 模式 附注2补码 附注3汇编编译器(masm.exe)对jmp的 相关处理 附注4用栈传递参数 附注5公式证明
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CCPigSnail

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值