20192429马一 2021-2022-2 《汇编语言程序设计》前四章学习报告
第一章 基础知识
1.1汇编语言的一般概念
1.机器语言
- 把控制计算机的命令和各种数据直接用二进制数码表示的一种语言
- 效率高,速度快,程序长度短
- 人类不方便识别
2.高级语言
- 将计算机内部的操作细节屏蔽,编制程序完成指定任务
- 程序设计简单,但效率低
3.汇编语言
- 使用十进制数或十六进制数来表示 数据
- 和硬件密切联系
汇编语言程序与机器语言程序指令对应,汇编语言程序与机器语言程序效率相同
1.2 学习和使用汇编语言的目的
- 从根本上认识、理解计算机的工作过程
- 在计算机系统中,某些功能必须用汇编语言程序来实现
- 汇编语言程序的效率高于高级语言程序
1.3 进位计数制及其相互转换
- 多位数码中每一位的构成方法以及从低位到高位的进位规则。
-
十进制转换为二进制
- 减权定位法:从二进制数高位起,依次用待转换的十进制数与各位权值进行比较;如果够减,则该数位系数Ki=1,同时减去该位权值,余数作为下一次比较的值
- 除基取余法:将十进制数除以基数2,其余数为二进制数的最低位,再用其商除2,其余数为次低位,反复直到商为0
-
二进制转换为十进制
- 按权相加法
- 逐次乘基相加法:从二进制数的最高位开始,将最高位的1乘以2并与次高位的数相加,之后将结果乘以2再与低一位相加,重复此过程直至最低位加入结果。
1.4带符号数的表示
原码
- 二进制数的最高位表示符号,0表示正,1表示负。数值部分用二进制数绝对值表示
补码
- 带符号数X的补码表示[X]补定义:[X]补 = M+X(Mod M),其中M为机器数的位数,例如位数为8则M=28,符号位仍然是0为正,1为负
- 对于正数,补码与原码相同,对于负数,将真值的各位取反再加一即可得到补码;或者将原码的符号位保持不变,其余各位取反再加一即可得到补码
运算规则:[X+Y]补 = [X]补+[Y]补
[X-Y]补 = [X]补-[Y]补 = [X]补+[-Y]补
1.5字符的表示
ASCII码
- 标准ASCII码为一字节,其中用低七位表示字符编码,用最高位作为奇偶校验位
- 标准ASCII码共有128个
- 非打印ASCII码(33个),用于控制操作
- 可打印ASCII码(95个)
1.6基本逻辑运算
- 计算机内部采用二进制数表示信息,而“0”和“1”正好对应逻辑“真”和“假”两个状态。
(1)“与”运算(AND)
(2)“或”运算(OR)
(3)“非”运算
(4)“异或”运算
- 通常用⨁表示,即 F=A⨁B,A与B相同时,F为1,否则F为0
第二章 IBM-PC微机
2.1 IBM-PC微机基本结构
(1)微机构成
- 运算器、控制器、存储器、I/O设备
- 运算器和控制器两大部件集成在一个集成电路芯片上,称为中央处理器,简称CPU
习惯上把CPU和主存储器合称为主机,在计算机中除了主存储器之外,一般还有辅助存储器,也称为外存。
- 系统采用总线结构,系统总线分为地址总线、数据总线、控制总线三类
I/O设备的工作速度、工作原理以及所处理的信息格式等与主机相差很大,因此I/O设备要通过I/O接口与系统总线连接
(2)Intel 8086/8088 CPU的功能结构
- 汇编语言程序由一系列指令构成,重复“取-执行”两个步骤
- 串行方式:系统总线空闲时间多
- 指令流水线方式:EU与BIU,效率高
2.2 CPU寄存器结构及用途
- CPU中的寄存器一共有14种,其中通用寄存器8个,控制寄存器2个,段寄存器4个。
(1)通用寄存器
- 通用性良好,可以用作某特定功能
- 数据寄存器:可以用来存放操作数也可以用来存放结果
- 指针寄存器(堆栈指针SP和基址指针BP)
- 变址寄存器(SI DI)
(2)段寄存器
- cpu在使用存储器的时候,将它分成了若干个段,但运行时最多只有四个段
- 每段用来存放不同的内容,如程序代码,数据等
- 每个存储段用一个段寄存器指明该段的起始位置
(3)指令指针IP
- 当CPU从内存中取出一条指令后,IP内容会自动修改为指向下一条指令。
(4)标志寄存器
- 用来反映cpu在程序运行时的某些状态
2.3 存储器组织结构
2.3.1 存储器的组成
- 存储器是由若干个存储单元构成
- 每个存储单元存放相同长度的二进制数
- 每个存储单元有一个唯一的地址编号——地址
- 为了方便书写,在源程序中常用5位十六进制数或一个符
号来表示一个存储单元的地址。
- 为了方便书写,在源程序中常用5位十六进制数或一个符
- 任何两个相邻字节单元就构成一个字单元
- 一个字存储单元(WORD)的长度为16位二进制数,即两个字节。字单元的地址为两个字节单元中较小地址字节单元的地址。
- 16位长数据的存放规则是低8位放在较低地址字节单元中,高8位放在较高地址字节单元中。
- 在定义一个地址时必须指出是字节或字类型属性
2.3.2 存储器的段结构
- 由于8086/8088可寻址的存储空间为1MB,需要提供20位长的地址码。而CPU内部的寄存器长度只有16位。能够直接访问的最大地址空间是64KB。
- 8086/8088CPU将1MB的存储空间划分成若干个段,每个段最大长度为64K(65536)个字节单元组成。
- 每个段的基址(段基址)必须是一个小节的首址。
- 逻辑段在物理存储器中可以是邻接的、间隔的、部分重叠的和完全重叠的等4种情况。
- 在任一时刻,一个程序只能访问4个当前段中的内容。
4个段分别是代码段、数据段、堆栈段和附加段,称为当前段 。4个段寄存器CS、DS、SS和ES分别保存了它们段基址的高16位地址,称为段基值。段基址的最低4位为0。(小节首址的低4位为全0 )。
2.3.3 物理地址与逻辑地址及其对应关系
- 物理地址
- CPU与存储器之间的任何信息交换都使用物理地址。
- 逻辑地址
- 一个逻辑地址包括两个部分:段基值和偏移量
段基值:存放在某一个段寄存器中,是一个逻辑段的起始
单元地址(段基址)的高16位。
偏移量:表示某个存储单元与它所在段的段基址之间的字
节距离。
- 转换
- 转换方法:将逻辑地址的段基值左移4位,形成20位的段基址(低位为0)然后与16位的偏移量相加,结果即为20位的物理地址。
2.4 堆栈及其操作方法
2.4.1 堆栈的构造
- 专用堆栈存储器 和 软件堆栈
- SP的内容始终指向栈顶单元
- 堆栈中数据进出都由SP来控制
2.4.2 8086/8088堆栈的组织
- 在8086/8088微机中堆栈是由堆栈段寄存器SS指示的一段存储区。
2.4.3 堆栈操作
- 设置堆栈
- 进栈 PUSH
- 出栈 POP
第三章 寻址方式与指令系统
3.1寻址方式
- 一条指令通常由两大部分构成:操作码和操作数
- 寻址方式:寻找指令中所需操作数的各种方法,也就是提供指令中操作数的存放信息的方式。
3.1.1 立即数寻址
- 立即数寻址方式的指令中,所需操作数直接包含在指令代码中,这种操作数称为立即数。
3.1.2 寄存器寻址
- 寄存器寻址方式是指指令中所需的操作数在CPU的某个寄存器中。寄存器可以是8位或16位通用寄存器,或者是段寄存器。如:AH、AL、AX、CX、DS、ES等。
由于存取寄存器操作数完全在CPU内部进行,不需要总线周期,所以执行速度很快。
3.1.3 直接寻址
- 用符号和常数表示
3.1.4 寄存器间接寻址
- 指示存储器所在段的段寄存器可以省略,当指令中使用的是BP寄存器,则隐含表示使用SS段寄存器,其余情况则隐含使用DS段寄存器。
3.1.5 基址寻址/变址寻址
- 由于这两种寻址方式中寄存器中的内容是相对于由位移量指定的初始单元。因此也叫寄存器相对寻址。
3.1.6 基址变址寻址
- EA=基址+变址+位移量
在基址变址寻址方式中,程序运行期间有两个地址分量可以修改。因此它是最灵活的一种寻址方式,可以方便地对二维数组进行访问。
3.1.7 串操作寻址方式
3.1.8 I/O端口寻址
- 直接端口寻址:在指令中直接给出端口地址,端口地址一般采用2位十六进制数,也可以用符号表示
- 寄存器间接端口寻址:把I/O端口的地址先送到DX中,用DX作间接寻址寄存器
3.2指令系统
- 一种计算机所能执行的各种类型的指令的集合称为该计算机的指令系统。
指令不需要操作数,如暂停指令HLT。
在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如指令PUSHF。
3.2.1 传送指令
- 将源操作数指定的内容传送到目的操作数,即DEST<=(SRC)。
1. 交换指令
- 源操作数和目的操作数两者内容相互交换,即:(DEST)<=>(SRC)。
- 指令对标志寄存器各位无影响
2. 标志传送指令
- 对标志寄存器进行存取的指令有4条,它们都是无操作数指令,即指令隐含指定标志寄存器、AH寄存器或堆 栈为操作数
3. 地址传送指令
- 把SRC存储单元开始的4个字节单元的内容(32位地址指针)送入DEST通用寄存器和段寄存器DS(LDS指令)或ES(LES指令),其中低字单元内容为偏移量送通用寄存器,高字单元内容为段基值送DS或ES。
3.2.2 算术运算类
1. 加法指令
- DEST和SRC不能都为存储器操作数。
- ADD指令可以是字节操作数相加,也可以是字操作数相加。
2. 带进位加法指令
- 根据相加的结果设置标志寄存器中的CF、PF、AF、ZF、SF和OF
3. 加1指令
- 目的操作数可以是任意的8位、16位通用寄存器或存储器操作数。目的操作数被视为带符号二进制数
4. 减法指令
- 目的操作数的内容减去源操作数的内容,结果送入目的操作数,源操作数中内容保持不变。
5. 带借位减法
- SBB指令在使用上与ADC类似,主要用于长度大于16位的数相减,即将低16位相减的结果引入高位部分的减法中。
6. 减1指令
- DEST可以是8位或16位的通用寄存器存储器操作数,该指令将DEST看作是带符号二进制数。
- DEC指令的使用类似INC指令。主要用于计数和修改地址指针,计数方向与INC指令相反。
7. 求负数指令
- 由于机器中带符号数用补码表示,求操作数的负数就是求补操作。因此,NEG指令也叫取补指令。
3.2.3 位操作类指令
1. 逻辑运算指令
- 逻辑指令对标志位的影响:
NOT指令对标志无影响。而其余三条指令将根据结果影响SF、ZF和PF,而CF和OF总 是置0,AF为不确定。
逻辑运算指令除用来实现各种逻辑运算之外,还常用于对字节或字数据的某些位的组合、分离或位设置
2. 测试指令
- TEST指令主要用于测试某一操作数的一位或几位的状态。
3. 移位/循环移位指令
- 算术移位
- 逻辑移位
- 循环移位、
为了保持其算术运算结果的正确性,移位后的结果不能发生溢出。
3.2.4 处理器控制类指令
- 它们都是无操作数指令,操作数隐含为标志寄存器的某个标志位。能直接操作的标志位有CF、IF和DF。
1. 标志位操作指令
2. 与外部事件同步的指令
3. 空操作指令 NOP
3.3 指令编码
3.3.1 双操作指令编码格式
一个操作数在寄存器中,另一操作数在寄存器或存储器中。
目的操作数在寄存器或存储器中,源操作数是立即数。
3.3.2 单操作数指令编码格式
- 这种编码格式适用于只有一个操作数的指令,如INC、DEC、移位/循环等指令。
V=0时,指令中使用常数1作为移位或循环次数。
V=1时,指令中使用寄存器CL作移位次数。
由于单操作数指令中只有一个操作数,因此寻址特征部分就不需要REG字段,而该字段被用作辅助操作码。
3.3.3 与AX或AL有关的指令编码格式
- 立即数:则编码中应有1~2字节的立即数
- 存储单元:只能使用直接寻址方式,位移量由disp字段给出。
第四章 汇编语言程序格式
汇编语言的语句可以分为指令语句和伪指令语句
4.1 汇编语言种类及其格式
4.1.1 指令语句
- 每一条指令语句在汇编时都要产生一个可供CPU执行的机器目标代码,它又叫可执行语句。
- 标号字段(可选)
- 指令助记符字段(必选项)
- 操作数字段:一条指令可以由一个操作数、两个操作数或无操作数
- 注释字段(“;”开始)
4.1.2 伪指令语句(命令语句)
- 符号名字段
- 伪指令符字段
- 该字段是伪指令语句的必选项,它规定了汇编程序所要完成的具体操作。
- 操作数字段
- 注释字段
4.1.3 标识符
- 标识符构成规则:
- 字符的个数为1~31个
- 第一个字符必须是字母、问号、@或下划线“_”这4种字符之一
- 从第二个字符开始,可以是字母、数字、@ 、 “_”或问号“?”
- 不能使用属于系统专用的保留字
保留字: CPU中各寄存器名(如AX、CS等),指令助记符(如MOV、ADD),伪指令符(如SEGMENT、DB)、表达式中的运算符(如GE、EQ)以及属性操作符(如PTR、OFFSET等)
4.2 汇编语言数据
- 在说明数据时不仅要指定其数值,还需说明它的属性,比如是字节数据还是字数据。
4.2.1 常数
- 二进制数、八、十、十六、实数、字符串常数
4.2.2 变量
- 程序中以变量名的形式来访问变量,因此,可以认为变量名就是存放数据的存储单元地址。
- 变量的定义与预置
段属性:它表示变量存放在哪一个逻辑段中。
偏移量属性:段属性和偏移量属性就构造了变量的逻辑地址
类型属性:它表示变量占用存储单元的字节数
- 变量的使用
在指令语句中引用:当变量出现在变址(基址)寻址或基址变址寻址的操作数中时表示取用该变量的偏移量。
在伪指令语句中引用
4.2.3 标号
- 标号主要用在程序中需要改变程序的执行顺序时,用来标记转移的目的地,即作转移指令的操作数。
- 每个标号具有三个属性:
段属性(SEG)
偏移量属性(PFFSET)
距离属性(类型属性)
4.3 符号定义语句
4.3.1 等值语句
语句格式:符号名 EQU 表达式
- 功能:用符号名来表示EQU右边的表达式。后面的程序中一旦出现该符号名,汇编程序将把它替换成该表达式。
- 表达式类型:
- 常数或数值表达式:COUNT EQU 5;NUM EQU COUNT+5
- 地址表达式:ADR1 EQU DS:[BP+14]
- 变量、寄存器名或指令助记符
- 在同一源程序中,同一符号不能用EQU定义多次。
4.3.2 等号语句
- 格式: 符号名 = 表达式
等号语句与等值语句具有相同的作用。但等号语句可以对一个符号进行多次定义。
等值语句与等号语句都不会为符号分配存储单元。
因此所定义的符号没有段、偏移量和类型等属性。
4.4 表达式与运算符
- 任何表达式的值在程序被汇编的过程中进行计算确定,而不是到程序运行时才计算。
4.4.1 算术运算符
- .运算符“+”和“-”也可作单目运算符,表示数的正负。
- 使用“+”、“-”、“*”、和“/”运算符时,参加运算的数和运算结果都是整数
- “/”运算为取商的整数部分,而“MOD”运算取除法运算的余数。
- “SHR ”和“SHL ”为逻辑移位运算符
移位运算符与移位指令区别。 移位运算符的操作对象是某一具体的数(常数),在汇编时完成移位操作。而移位指令是对一个寄存器或存储单元内容在程序运行时执行移位操作。
- 下标运算符“[ ]”具有相加的作用
4.4.2 逻辑运算符
NOT、AND、OR和XOR
4.4.3 关系运算符
- 关系运算符用来比较两个表达式的大小。关系运算符比较的两个表达式必须同为常数或同一逻辑段中的变量。
- 关系运算的结果只能是“真”(全1)或“假”(全0)
4.4.4 数值返回运算符
- SEG运算符:取变量或标号所在段的段基值
- OFFSET运算符:是取变量或标号在段内的偏移量。
- TYPE运算符:取变量或标号的类型属性,并用数字形式表示
- LENGTH运算符:取变量的长度
如果变量是用重复数据操作符DUP说明的,则LENGTH运算取外层DUP给定的值
如果没有用DUP说明,则LENGTH运算返回值总是1
- SIZE运算符:只能作用于变量,SIZE取值等于LENGTH和TYPE两个运算符返回值的乘积。
4.4.5 属性修改运算符
- PTR运算符: 将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为 “类型”所指的值。
- HIGH/LOW运算符:将表达式的值分离出高字节和低字节
如果表达式为一个常量,则将其分离成高8位和低8位
如果表达式是一个地址(段基值或偏移量)时,则分离出它的高字节和低字节
HIGH/LOW运算符不能用来分离一个变量、寄存器或存储器单元的高字节与低字节。
- THIS运算符:所定义的变量或标号的段基值和偏移量与紧跟其后的变量或标号相同
标号LFAR与LNEAR具有相同的逻辑地址值,但类型不同。LNEAR只能被本段中的指令调用,而LFAR可以被其它段的指令调用。
4.4.6 运算符的优先级
可以用圆括号改变运算顺序
4.5 程序的段结构
4.5.1 段定义伪指令
段名 SEGMENT [定位类型] [组合类型] [‘类别名']
…...
... ... 本段语句序列
… ...
段名 ENDS
- 段名:一个段的开始与结尾用的段名必须一致。
- 定位类型
PAGE: 表示该段从一个页面的边界开始
PARA:表示该段从一个小节的边界开始
WORD:表示该段从一个偶数字节地址开始,即段起始单元地址的最后一位二进制数一定是0。
BYTE:表示该段起始单元地址可以是任一地址值
定位类型为PAGE和PARA时,段起始地址与段基址相同。定位类型为WORD和BYTE时,段起始地址与段基址可能不同。
- 组合类型
若未指定组合类型,表示本段与其它段无连接关系
PUBLIC:在满足定位类型的前提下,将与该段同名的段邻接在一起,形成一个新的逻辑段,共用一个段基址
COMMON: 产生一个覆盖段。在多个模块连接时,把该段与其它也用COMMON说明的同名段置成相同的段基址,这样可达到共享同一存储区。共享存储区的长度由同名段中最大的段确定
STACK:把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP
AT表达式:表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值。
MEMORY:表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用MEMORY说明的段,则只处理第一个用MEMORY说明的段。其余的被视为COMMON
- 类别名
- 类别名必须用单引号引起来。所用字符串可任意选定,但它不能使用程序中的标号、变量名或其它定义的符号。
在定义一个段时,段名是必须有的项,而定位类型、组合类型和类别名三个参数是可选项。各个参数之间用空格分隔。各参数之间的顺序不能改变
4.5.2 段寻址伪指令
- 段寻址伪指令ASSUME的作用是告诉汇编程序,在处理源程序时,定义的段与哪个寄存器关联。
4.5.3 段寄存器的装入
- DS和ES的装入
- 在程序中,使用数据传送语句来实现对DS和ES的装入。
- SS的装入
- 在段定义伪指令的组合类型项中,使用STACK参数,并在段寻址伪指令ASSUME语句中把该段与SS段寄存器关联
- CS的装入
- 由系统软件按照结束伪指令指定的地址装入初始的CS和IP
- 在程序运行期间,当执行某些指令时,CPU自动修改CS和IP,使它们指向新的代码段
4.6 过程定义伪指令
每一个过程中必须包含有返回指令RET,其作用是控制CPU从子程序中返回到调用该过程的主程序。
4.7 当前位置计数器与定位伪指令
- 在源程序中,使用符号\(来表示位置计数器的当前值。因此,\)被称为当前计数器。它位于不同的位置具有不同的值。
将数值表达式的值赋给当前位置计数器$ 。ORG语句为其后的数据或指令设置起始偏移量。
4.8 标题伪指令TITLE
给所在程序指定一个标题。以便在列表文件的每一页的第一行都显示这个标题其中标题是用户任意选用的字符串,字符个数不能超过60。
4.9 从程序返回操作系统的方法
- 为了使程序运行结束后,能够正确地返回到操作系统,需要在程序中加上一些必要的语句。
- 使用程序段前缀PSP(Program Segment Prefix)实现返回
将用户程序编制成一个过程,类型为FAR
将PSP的起始逻辑地址压栈,即将INT 20H指令的地址压栈
在用户程序结尾处,使用一条RET指令。执行该指令将使保存在堆栈中的PSP的起始地址弹出到CS和IP中
- 使用DOS系统功能调用实现返回
- 执行DOS功能调用4CH,也可以控制用户程序结束,并返回DOS操作系统。