王爽《汇编语言第二版》学习笔记

目录

1 基础知识

2 寄存器

2.1 通用寄存器

  • 8086CPU的寄存器都是16位的
  • AX、BX、CX、DX4个通用寄存器

2.3 几条汇编指令

  • 汇编指令或寄存器的名称不区分大小写

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

  • 通过两个16位地址合成一个20位物理地址
  • 物理地址=短地址*16+偏移地址

2.5 段的概念

  • 内存并没有分段,段的划分来自于CPU
  • 编程时按照需要,将若干地址连续的内存单元看做一个段

2.6 段寄存器

  • 4个段寄存器:CS、DS、SS、ES
  • CS为代码段寄存器,IP为指令指针寄存器
  • 任意时刻,CS:IP将指向的内容当做指令执行

2.7 修改CS、IP的指令

  • 能够改变CS、IP的指令被称为转移指令
  • jmp 段地址:偏移地址
  • jmp 合法寄存器(仅修改IP)

3 寄存器(内存访问)

3.1 DS和[addr]

  • DS寄存器通常用来存放要访问的数据的段地址
  • [...]表示一个内存单元,...表示内存单元的偏移地址
  • 8086CPU不支持直接将数据送入段寄存器

3.2 CPU的栈机制

  • CPU的入栈和出栈都是以字为单位进行的
  • 任意时刻,SS:SP指向栈顶
  • push和pop也可以在内存单元之间传送数据

3.3 栈段

  • 一段内存,既可以是存代码,也可以存数据,也可以是栈空间,关键在于CS\IP、DS、SS\SP的指向

4 第一个程序

4.1 源程序

  • 源程序由指令、伪指令和标号组成

4.2 伪指令

  • 伪指令是由编译器来执行的指令,编译器根据伪指令来进行相关的编译工作

  • segment

  • end

  • assume

4.3 标号

  • 标号代表一个地址,segment前的标号被处理为一个段地址

4.4 程序返回

  • mov ax, 4c00H
  • int 21H

4.5 语法错误和逻辑错误

  • 编译时出现的错误是语法错误
  • 运行时发生的错误是逻辑错误

4.6 EXE文件中程序的加载过程

  • 找到一段起始地址为SA:0的内存空间
  • 在该区域内前256个字节,创建程序段前缀(PSP)的数据区,DOS利用PSP和程序进行通信
  • 从第256字节处开始,装入程序
  • 将该内存区的段地址存入DS,设置CS:IP指向程序入口(该内存区256字节处)

5 [BX]和loop指令

  • 要完整描述内存单元:需要内存单元地址和长度(类型)
  • [bx]表示一个内存单元,bx存储偏移地址,ds存储段地址
  • 定义的描述符号“()”:(ax)表示ax中的内容,(20000H)表示内存20000H单元中的内容(括号内为物理地址)
  • 约定符号idata表示常量

5.1 loop指令

  • CPU指令loops时,要进行两步:cx-1,若cs不为0跳转至s处指令,若为0向下执行

  • 用mov设置cx的值,表示循环次数

5.2 masm对指令的处理

  • mov al, ds:[0]
  • mov al, [bx] (段地址默认在ds中)

5.3 算和问题

  • 将内存单元中的8位数据赋值到16位寄存器ax中,再将ax中的数据加到dx上,从而使两个运算对象的类型匹配且结果不超界

5.4 段前缀

  • 用于显式地指明内存单元段地址的"ds:"被称为段前缀

6 包含多个段的程序

6.1 在代码段中使用数据

  • dw定义字型数据,db定义字节型数据,dd定义双字型数据
  • 也可以说dw开辟了内存空间
  • 在end start中,start标号指明了程序入口

6.2 可执行文件的程序执行过程

  • 由其他程序Debug、command等将程序加载到内存
  • 设置CS:IP指向程序入口
  • 程序运行结束,返回加载者

6.3 可执行文件的组成

  • 可执行文件由描述信息和程序组成
  • 描述信息主要是编译、链接过程中对程序的伪指令进行处理获得的
  • 加载者从描述信息中获取程序的入口地址

6.4 将数据、代码、栈放入不同的段

  • 段名也是标号,代表了段地址,mov ax, data
  • start在code段中,这样CPU就将code段中的内容当做指令执行(CS不用设置,栈和数据段都需设置段地址)

7 更灵活的定位内存地址的方法

7.1 and和or指令

  • and按位与,可用于置0
  • or按位或,可用于置1

7.2 [bx+idata]

  • 表示一个内存单元
  • 进行数组处理

7.3 SI和DI

  • SI和DI类似于BX,但不能分为两个8位寄存器

7.4 [bx+si/di+idata]

  • mov ax, [bx+si+200]

  • mov ax, 200[bx][si]

  • mov ax, [bx][si].200

  • 需要暂存数据的时候,一般用栈,比如双重循环的cx计数问题

8 数据处理的两个基本问题

  • 数据在哪里,有多长
  • reg表示寄存器,sreg表示段寄存器

8.1 bx、si、di和bp

  • 只有这四个寄存器能放在[...]中进行内存单元的寻址
  • 要么单独出现,要么以下四个组合:bx\bp和si、bx\bp和di
  • 只要在[...]中使用bp,默认的段地址在ss中

8.2 机器指令处理的数据在哪里

  • CPU内部、内存和端口

8.3 汇编语言中数据位置的表达

  • 立即数、寄存器、段地址和偏移地址

8.4 寻址方式

  • 用于定位内存单元的方法称为寻址方式
  • 直接寻址
  • 寄存器间接寻址
  • 寄存器相对寻址
  • 基址变址寻址
  • 相对基址变址寻址

8.5 要处理的数据有多长

  • 指令可以处理字节和字两种尺寸的数据
  • 通过寄存器名指明要处理的数据尺寸
  • 没有寄存器名的情况下,通过word/byte ptr指明内存单元长度

8.6 dup

  • 和db、dw、dd等数据定义伪指令配合使用,用来进行数据重复

9 转移指令的原理

  • 只修改IP,称为段内转移
  • 都修改,称为段间转移
  • 段内转移分为短转移和近转移
  • CPU的转移指令类型:无条件、有条件、中断、过程、循环

9.1 操作符offset

  • 功能是获取标号的偏移地址

9.2 根据位移进行转移的jmp指令

  • jmp short 标号
  • 机器码中包含的是转移的位移
  • jmp near ptr 标号

9.3 转移的目的地址在指令中的jmp指令

  • jmp far ptr标号是段间转移,又称为远转移

9.4 转移地址在寄存器中的jmp指令

9.5 转移地址在内存中的jmp指令

  • jmp word ptr 内存单元地址 (取偏移地址)
  • jmp dword ptr 内存单元地址 (高地址是段地址,低地址是偏移地址)

9.6 jcxz指令

  • jcxz为有条件转移指令,所有条件转移指令都是短转移
  • cx=0则跳转到标号

9.7 屏幕显示颜色字符

  • 显存中有一块80*25的彩色字符模式显示缓冲区,向该内存中写入数据,内容可以立即显示到显示器上
  • 一个字符占两个字节,一个字节存放arscii码,一个字节存放属性

10 CALL和RET指令

10.1 ret和retf

  • ret用栈中数据修改IP,实现近转移
  • retf用栈中数据修改CS:IP,实现远转移

10.2 call指令

  • 将IP和CS入栈
  • 转移

10.3 根据位移转移

  • call 标号 (近转移)

10.4 根据目的地址进行转移

  • call far ptr (段间转移)

10.5 转移地址在寄存器中的call指令

  • call 16位reg

10.6 转移地址在内存中的call指令

  • call word ptr 内存单元地址
  • call dword ptr 内存单元地址

10.7 子程序

  • 模块化程序设计

  • call和ret配合实现子程序

  • 使用寄存器传参,或者使用栈传参

  • 在子程序开始时,将要用到的寄存器中内容全部入栈,退出时恢复,用来解决寄存器冲突问题

11 标志寄存器

  • 8086的标志寄存器flag有16位,其中的信息被称为程序状态字(PSW)
  • flag寄存器是按位起作用的

11.1 ZF标志

  • 零标志位

11.2 PF标志

  • 奇偶标志位

11.3 SF标志

  • 符号标志位
  • 做有符号数的运算时,可以通过它来得知结果正负
  • 无符号数运算时,会影响值,但无意义

11.4 CF标志

  • 借位或进位标志位
  • 用于无符号数运算

11.5 OF标志

  • 溢出标志位
  • 用于有符号数运算

11.6 adc指令

  • 带进位的加法
  • adc和add配合可以对更大的数据进行加法

11.7 sbb指令

  • 带借位的减法

11.8 cmp指令

  • cmp a, b,计算差,但不保留结果,只影响flag寄存器
  • 比较无符号数,看zf和cf
  • 比较有符号数,看sf和of

11.9 条件转移指令

  • 和cmp配合使用
  • 根据无符号数比较结果进行转移:je、jne、jb、jnb、ja、jna
  • 二者配合使用时不用考虑标志寄存器,只用考虑逻辑含义

11.10 DF标志和串传送指令

  • DF是方向标志位,在串处理指令中,控制每次操作后si和di的增减
  • DF=0是递增,DF=1是递减
  • movsb将ds:si指向的内存单元中的字节送入es:di中,然后根据df值,控制si\di增减
  • movsw是传送字单元
  • rep movsb根据cx的值,重复执行后面的串传送指令
  • cld和std

11.11 pushf和popf

  • 用于将标志寄存器入栈和出栈

12 内中断

12.1 内中断的产生

  • 用中断类型码表示256种中断信息的来源
  • 除法错误:0
  • 单步执行:1
  • 执行into指令:4
  • 执行int n指令:n

12.2 中断向量表

  • 用中断类型码通过中断向量表找到中断处理程序的入口地址

  • 中断向量表在内存中保存,存放256个中断源对应的中断处理程序的入口地址

  • 一个表项占两个字,高地址字存放段地址,低地址字存放偏移地址

12.3 中断过程

  • CPU收到中断信息后,引发中断过程,之后将CS:IP指向程序入口,开始执行中断处理程序
  • 中断过程:取得中断类型码,标志寄存器入栈,TF和IF置0,CS:IP入栈,读取程序入口地址
  • 中断过程由硬件完成

12.4 中断处理程序和iret指令

  • 中断处理程序步骤:保存用到的寄存器,处理中断,恢复用到的寄存器,用iret返回
  • iret:pop cs, pop ip, popf

12.5 编程处理0号中断

  • 0000:0000~0000:03ff空间中存放中断向量表,不会被其他程序使用
  • 可以用0000:0200~0000:02ff的空间来存放中断处理程序
  • 步骤:编写中断处理程序do0,将do0传送到目标内存,将do0入口地址写入0号表项

12.6 do0的安装

  • 用rep movsb传送do0的字节
  • 偏移地址是offset do0
  • 通过编译器计算do0长度:offset do0end-offset do0
  • do0end: nop
  • 汇编编译器可以处理表达式

12.7 单步中断

  • CPU执行完一条指令后,如果检测到TF=1,则产生单步中断
  • 解释了为什么在中断过程中要将TF置0:避免CPU永远执行单步中断程序的第一条指令
  • CPU提供单步中断功能为跟踪程序的执行过程,提供了实现机制

12.8 响应中断的特殊情况

  • 设置ss和sp的指令连续存放,为避免指向错误栈顶,CPU在两条指令之间不会引发中断过程

13 int指令

13.1 int指令

  • CPU执行int n指令,相当于引发一个n号中断的中断过程
  • 系统将一些具有一定功能的子程序,以中断处理程序的方式提供给应用程序调用,又称为中断例程

13.2 BIOS和DOS中断例程的安装过程

  • 开机后,CPU加电,初始化CS:IP,自动从FFFF:0单元开始执行程序,该处有一条跳转指令,专区执行BIOS的硬件系统检测和初始化程序
  • 初始化程序将建立BIOS所支持的中断向量,中断例程已固化到ROM中,一直在内存中
  • 调用int 19H进行操作系统的引导,将操作系统从磁盘上加载到内存中,从此将计算机交给操作系统控制
  • DOS启动后,将它所提供的的中断例程装入内存,并建立中断向量

13.3 BIOS中断例程应用

  • BIOS和DOS提供的中断例程,都用ah来传递内部子程序的编号

13.4 DOS中断例程应用

  • mov ah, 4ch; 程序返回功能
  • mov al, 0; 返回值
  • int 21h; 中断

14 端口

  • CPU在操控存储器时,把它们总的看做一个内存地址空间

  • 和CPU通过总线相连的芯片除了存储器,还有各种接口卡上的接口芯片和主板上的接口芯片(连接外设)

  • 这些芯片中,都有一组CPU可读写的寄存器,即端口

  • CPU的角度,对这些端口进行统一编址,建立了统一的端口地址空间

  • CPU可从以下三个地方读写数据:CPU内部寄存器、内存单元、端口

14.1 端口的读写

  • 范围0~65535
  • 读写指令in和out
  • 只能使用ax或al从端口读入数据或发送数据,访问8位端口时用al,16位用ax
  • 对256~65535的端口读写时,端口号要放到dx中

14.2 CMOS RAM芯片

  • PC机中,有一个CMOS RAM芯片,靠电池供电,关机后内部实时时钟仍然工作
  • 0~0dh单元用于保存时间信息,其余大部分单元用来保存系统配置信息,供系统启动时BIOS程序读取
  • 两个端口,70h用来存放访问RAM单元的地址,71用来存放访问的数据

14.3 shl和shr指令

  • shl是逻辑左移指令,左移一位,移出的送到CF中,最低位用0补充
  • 如果移动位数大于1时,必须将移动数放到cl中

15 外中断

  • CPU通过端口和外部设备进行联系

15.1 外中断信息

  • 外设的输入放到端口后,相关芯片向CPU发出中断信息,引发中断过程,处理外设的输入

(1)可屏蔽中断

  • CPU可以不响应的外中断,IF=0,不响应可屏蔽中断
  • 可屏蔽中断的中断过程和内中断相同,只是中断类型码是通过数据总线送入CPU,而内中断类型码是在CPU内部产生的
  • sti和cli可以设置IF位

(2)不可屏蔽中断

  • CPU必须响应的外中断
  • 中断类型码固定为2
  • 几乎所有由外设引发的外中断,都是可屏蔽中断

15.2 PC机键盘的处理过程

(1)键盘输入

  • 每个按键相当于一个开关,芯片对每个键的开关状态进行扫描

  • 按下按键后,产生扫描码(通码),送入60h端口

  • 松开按键后,产生扫描码(断码),送入60h端口

(2)引发9号中断

  • 送入60h端口后,芯片向CPU发出9号中断,CPU响应中断,引发中断过程,执行int 9中断例程

(3)执行int 9中断例程

  • 进行基本的键盘输入处理,如果是字符键,将扫描码和对应的arscii码送入内存中的BIOS键盘缓冲区;如果是控制键,写入存储状态字节的单元

15.3 编写int 9中断例程

  • int过程可以模拟为:

  • 标志寄存器入栈,TF=1、IF=1,call dword ptr ds:[0]

  • 端口和中断机制,是CPU进行IO的基础

16 直接定址表

16.1 描述单元长度的标号

  • a db 1,2,3

  • 标号a后没有“: ”,它是同时描述内存地址和单元长度的标号,可以代表内存单元

  • mov al, a[bx+si+3]

  • a被称为数据标号,而带": "的被称为地址标号(只能在代码段中使用)

16.2 在其他段中使用数据标号

  • 如果想在代码段中直接使用其他段的数据标号访问数据,需要指定该段的段寄存器和段地址

(1)存储标号偏移地址

  • c dw a
  • 此时数据标号c处存储的字型数据为a的偏移地址
  • 相当于 c dw offset a

(2)存储标号偏移地址和段地址

  • c dd a
  • 此时数据标号c处存储的双字型数据为a的偏移地址和段地址
  • 相当于c dw offset a, seg a

16.3 直接定址表

  • table db '0123456789ABCDEF'
  • 利用表,可以直接在两个集合(数字集合和字符集合)之间建立映射关系,通过查表,根据给出的数据(如0),可以得到其在另一集合中对应的数据(如'"0"')
  • 通过数据,直接计算出所要找的元素的位置(表内偏移)的表,称为直接定址表

17 使用BIOS进行键盘输入和磁盘读写

  • BIOS为这两种外设的IO提供了最基本的中断例程

17.1 键盘处理

  • int 9中断例程在有键按下时向键盘缓冲区写入数据
  • int 16h中断例程在应用程序对其调用时,将数据从键盘缓冲区读出

17.2 磁盘读写

  • 设置参数后,调用int 13h

18 CPU的三种工作模式

18.1 实模式

  • 实模式下,指令直接访问物理地址,通过段地址*16+偏移地址获得物理地址

18.2 保护模式

  • 为了实现进程隔离和多任务并发,引入了保护模式,同时为实现虚拟内存提供了硬件支持

  • 通过分段和分页机制来进行保护和隔离

(1)分段和分页

  • 分段:引入GDT(全局描述符,即段表),表中的表项称为段描述符,段寄存器中存放索引(段选择子),通过索引找到表项,获取段信息,加上偏移地址得到线性地址,目的是在寻址过程中保存保护信息(比如内存段属性)

  • 分页:将虚拟内存划分为大小相同的页,同时物理空间也分为若干个物理块(页框),二者大小相等,离散分配,通过MMU查页表,实现页号到物理块号的映射,目的是将内存分块,将暂时不用的块放到磁盘上,扩展空间

  • 分段是必须的,分页不是必须的

  • 段是二维的,大小不固定,页是一维的,大小固定

  • 保护模式下,每个段都设置了特权级,高特权级的代码可以对地特权级数据进行访问

(2)四种地址

  • 虚拟地址是没有经过分段和分页转化的地址,是段寄存器和变址寄存器的组合

  • 逻辑地址是用户可以操作的地址,即偏移地址

  • 线性地址是虚拟地址经过分段转化后的地址,可以定位虚拟内存

  • 物理地址是线性地址经过分页转化后的地址

18.3 虚拟8086模式

  • 使用户可以方便地在保护模式下运行一个或多个原8086程序

  • DOS系统中,CPU以实模式运行

  • Windows系统中,CPU以保护模式运行

  • 想在Windows中运行DOS程序,CPU切换至虚拟8086模式

19 实验

19.1 屏幕显示颜色字符

19.2 利用栈倒序存储字符串

19.3 编程处理0号中断

20 附录

  • 数据可以分为字符和数字两种类型,在内存中都以二进制形式存储,其中字符存储arscii码(一个字节),数字存储补码(长度由具体数字类型决定)
  • 关于内存单元的地址和内容:地址表示在几个字节处,内容表示存储了什么字节
posted @ 2022-10-03 21:03  z5onk0  阅读(120)  评论(0编辑  收藏  举报