20192417张家华 汇编语言前四章笔记
第一章 基础知识
1.1 汇编语言的一般概念
机器语言:把控制计算机的命令和各种数据直接用二进制数码表示的程序设计语言
高级语言:将计算机内部的操作细节屏蔽起来
汇编语言:使用字母和符号来表示机器语言的命令,用十进制数或十六进制数来表示数据
2.进位计数制及其相互转换
B 二进制数
O或Q 八进制数
D 十进制数
H 十六进制数
3.带符号数的表示
真值:用“+”或“-”表示正负的数
机器数:用0或1表示正负的数
原码:最高位用0/1表示,0有两种表示形式
补码:正数补码与原码相同,负数原码符号位不变,各位取反最低位加1,0的八位补码只有一个
【X-Y】补=【X】补+【-Y】补,求补:连同符号位按位取反,最低位加1
4.字符的表示
ASCII码:一字节,最高位表示奇偶校验位,低七位表示字符编码;共128个,非打印33个
5.基本逻辑运算
与 或 非 异或
第二章 微机结构
1. IBM-PC微机基本结构
基本结构:
中央处理器:CPU,微处理器,包括运算器和控制器
主存储器:存放程序和数据,由若干个存储单元构成
将CPU与主存储器合称为主机
I/O设备与接口
系统总线:包括地址总线、数据总线和控制总线
功能结构:
CPU执行指令:
1.从存储器中取指令
2.执行指令规定的操作
串行方式:计算机运行速度慢
指令流水线方式:划分为执行单元和总线接口单元
2.CPU寄存器结构及其用途
1.通用寄存器:
数据寄存器:包括AX、BX、CX、DX四个寄存器;存放操作数或运算结果
隐含使用:在某些指令中,不需要明确指出使用的寄存器名,即隐含使用对应寄存器,例如在循环指令LOOP中,CX被隐含 指定作循环次数计数用;
特定使用:必须在指令中指明它的名字,例如移位指令SHL AX,CL, CL被固定用作移位次数。
指针寄存器:有堆栈指针SP和基址指针BP
SP指针——在进行堆栈操作时被隐含使用,用来指向堆栈顶部单元
BP指针——被用来指向堆栈段内某一存储单元
变址寄存器:有两个16位的变址寄存器SI(源变址寄存器)和DI(目的变址寄存器),一般被用来作地址指针
2.段寄存器:每个存储段用一个段寄存器来指明该段的起始位置(也叫段基址)
CPU访问存储单元需指明:段基址、偏移量
3.指令指针IP
CPU从存储器取指令时,以段寄存器CS作为代码段的基址指针,以IP的内容作为偏移量,共同形成一条指令的存放地址
当CPU从内存中取出一条指令后,IP内容自动修改为指向下一条指令
4.标志寄存器
用来反映CPU在程序运行时的某些状态,如是否有进位、奇偶性、结果的符号、结果是否为零
长度为16位但只定义9位
进位标志位CF:在算术运算时,若最高位(字操作的第15位,字节操作的第7位)产生进位或借位时CF被自动置“1”;在移 位指令中,CF用来存放左移最高位或右移最低位移出的数值
奇偶标志位PF:当指令操作结果的低8位中含有1的个数为偶数时,PF置1,否则置0
辅助进位标志位AF:在算数运算时,若低字节的低四位向高四位产生进位或借位,AF置1,否则置0
零值标志位ZF:结果各位全为0,则ZF置1,否则置0
符号标志位SF:运算结果为负数时置1,为正数时置0
溢出标志位OF:当运算结果超过机器用补码所能表示数的范围时,OF置1,否则置0
对于字节数据,机器用补码所能表示数的范围为-128 ~ +127
对于字数据,机器用补码所能表示数的范围为-32768 ~ +32767
单步标志位TF:也叫跟踪位,供调试程序使用
中断允许标志位IF:IF为1,CPU可以响应可屏蔽中断,否则不允许响应可屏蔽中断
方向标志位DF:用来规定串操作指令的增减方向。DF=0时,串操作指令自动使变址寄存器(SI和DI)的值递增;DF=1 时,串操作指令自动使变址寄存器的值递减
3.存储器组织结构
1.存储器的组成
任何两个相邻的字节单元构成一个字单元(WORD),地址为较小地址字节单元的地址。
在存储器中规定从0地址开始,每16个字节单元称为一个小节(paragraph),每个段的基址必须是一个小节的首地址。1MB内存可划分为64K个小节。
2.逻辑地址与物理地址及对应关系
物理地址:在1MB的存储空间中,每个存储单元的物理地址是唯一的(20位地址)。
逻辑地址:包含段基值(段基址的高16位)和偏移量两个部分
逻辑地址转换为物理地址:将逻辑地址的端基值左移4位,形成20位的段基址(低4位为0)然后与 16位的偏移量相加,结果即为20位的物理地址
4.堆栈及其操作方法
堆栈用途:主要用于暂存数据以及在过程调用或处理中断时保存断点信息
一般分为:专用堆栈存储器和软件堆栈
堆栈操作
1.设置堆栈:主要是对堆栈段寄存器SS和堆栈指针SP赋值
2.进栈PUSH
(1)将堆栈指针SP-2,即指向一个空的堆栈字单元
(2)将要储存的内容送入SP指向的字单元中
3.出栈POP
(1)将SP指向的字单元内容送往指定的寄存器或存储器
(2)将堆栈指针SP内容+2
第三章 寻址方式与指令系统
1.寻址方式
一条指令由操作码和操作数两部分组成
Intel 8086/8088各指令中提供操作数的方法有四种:
立即数操作数: 操作数在指令代码中提供,可以是8位,也可以是16位
寄存器操作数: 操作数在CPU的通用寄存器或段寄存器中
存储器操作数: 操作数在内存的存储单元中
I/O端口操作数:操作数在输入/输出接口的寄存器中
1.立即数寻址
2.寄存器寻址
下面四种寻址方式是由三个地址分量的不同组合所形成的(1123)
3.直接寻址:操作数的有效地址EA只有位移量地址分量
4.寄存器间接寻址:操作数有效地址EA直接从基址寄存器(BX或BP)或变址寄存器(SI或DI)中 获得
在程序运行期间,只要对寄存器内容进行修改,就可以实现用同一条指令实现对不同存储单元进行操作。
5.基址寻址/变址寻址:操作数的有效地址EA等于基址分量或变址分量加上指令中给出的位移量
6.基址变址寻址:操作数的有效地址是三个地址分量之和,即:EA = 基址+变址+位移量
7.串操作寻址方式
在寻找源操作数时,隐含使用SI作为地址指针。
在寻找目的串时,隐含使用DI作为地址指针。
在串操作完成之后,自动对SI和DI进行修改,使它们指向下一个操作数。
8.I/O端口寻址
存储器编址方法:将I/O端口视为存储器的一个单元,对端口的访问就如同访问存储单元一样。访问存储器的指令和各种寻址方式同样适用对I/O端口的访问。
I/O端口编址方法:I/O端口的地址与存储器地址分开,并使用专门的输入指令和输出指令。
直接端口寻址:在指令中直接给出端口地址,端口地址一般采用2位十六进制数,也可以用符号表示。直接 端口寻址可访问的端口数为0~255个
寄存器间接端口寻址:把I/O端口的地址先送到DX中,用DX作间接寻址寄存器;如果访问的端口地址值大 于255,则必须用I/O端口的间接寻址方式
2.指令系统
从指令的格式划分,一般可以分为三种:
-
双操作数指令:OPR DEST SRC
-
单操作数指令:OPR DEST
-
无操作数指令:OPR
对于无操作数指令,包含两种情况:
1.指令不需要操作数,如暂停指令HLT 2.在指令格式中,没有显式地指明操作数,但是它隐含指明了操作数的存放地方,如指令PUSHF
从指令作用划分,可以分为六大类:
1.传送类指令:将数据信息或地址信息传送到一个寄存器或存储单元中,分为以下四种情况:
(1)通用数据传送指令:格式:MOV DEST,SRC,将源操作数指定的内容传送到目的操作数
三种情况:
立即数传送到通用寄存器或存储单元
寄存器之间的传送
寄存器与存储单元之间传送
(2)交换指令:格式:XCHG DEST,SRC,将源操作数和目的操作数两者内容相互交换
可以在寄存器之间或寄存器与存储器单元之间进行,但是不能在存储单元之间直接进行数据交换,应当使用 一个寄存器通过两次寄存器与存储单元之间的交换完成。
(3)标志传送指令:对标志寄存器进行存取
有4条,都是无操作数指令,即指令隐含指定标志寄存器、AH寄存器或堆栈为操作数
取标志寄存器指令,格式:LAHF
功能:将标志寄存器的低8位送入AH寄存器,即将标志 SF、ZF、AF、PF和CF分别送入AH的第7、6、4、2、0 位, 而AH的第5、3、1位不确定。指令执行对标志寄存器各位无影响
存储标志寄存器指令,格式:SAHF
功能:将寄存器AH中的第7、6、4、2、0位分别送入标志寄 存器的SF、ZF、AF、PF和CF各标志位。而标志寄存器高 8 位中的各标志位不受影响
标志进栈指令,格式:PUSHF
功能:先将堆栈指针SP减2,使其指向堆栈顶部的空字单元,然后将16位标志寄存器的内容送SP指向的字单元
标志出栈指令,指令格式:POPF
功能:将由SP指向的堆栈顶部的一个字单元的内容送 入标志寄存器,然后SP的内容加2
(4)地址传送指令:将存储单元的地址送寄存器
装入有效地址,格式:LEA DEST,SRC,源操作数SRC必须是一个字节或字存储器操作数 (地址),DEST必须是一个16 位通用寄存器。
功能:将SRC存储单元地址中的偏移量,即有效地址EA传送到一个16位通用寄存器中。指令执行对标志寄 存器各位无影响
装入地址指针指令,格式:LDS DEST,SRC; LES DEST,SRC。DEST是任意一个16位通用寄存器。SRC必须是一个 存储器操作数。
功能:把SRC存储单元开始的4个字节单元的内容(32位地址指针)送入DEST通用寄存器和段寄存器 DS(LDS指令)或ES(LES指令),其中低字单 元内容为偏移量送通用寄存器,高字单元内容 为段基值送DS或ES
2.算术运算类指令
加法指令,格式:ADD DEST,SRC。
带进位加法指令,格式:ADC DEST,SRC,功能与ADD基本相同,所不同的是其结果还要加上进位标志CF的值
加1指令,格式:INC DEST
减法指令,格式:SUB DEST,SRC
带借位减法,格式:SBB DEST,SRC
减1指令,格式:DEC DEST
求负数指令,格式:NEG DEST
对进位标志CF的影响:只有当操作数为零时,进位标志CF被置零,其它情况都被置1
对溢出标志OF的影响:当字节操作数为-128,或字操作数为-32768时,执行NEG指令的结果操作数将无变化,但溢出 标志OF被置1
由于机器中带符号数用补码表示,求操作数的负数就是求补操作。因此NEG指令也叫取补指令
3.位操作类指令
(1)逻辑运算指令
逻辑“与”指令 AND DEST, SRC
逻辑“或”指令 OR DEST, SRC
逻辑“异或”指令 XOR DEST, SRC
逻辑“非”指令 NOT DEST
(2)测试指令,格式:TEST DEST, SRC,主要用于测试某一操作数的一位或几位的状态
功能与AND指令相似,对标志位的影响与AND指令相同,但运算的结果不送入目的操作数。
(3)移位/循环移位指令,8条3类:
算术移位
算术左移 SAL DEST,COUNT
算术右移 SAR DEST,COUNT
逻辑移位
逻辑左移 SHL DEST,COUNT
逻辑右移 SHR DEST,COUNT
循环移位
小循环
循环左移 ROL DEST,COUNT
循环右移 ROR DEST,COUNT
大循环
带进位循环左移 RCL DEST,COUNT
带进位循环右移 RCR DEST,COUNT
4.处理器控制类指令
标志位操作指令:
清除进位标志CLC:置CF为0
置1进位标志STC:置CF为1
进位标志取反CMC:CF的值取反
清除方向标志CLD:置DF为0
置1方向标志STD:置DF为1
清除中断标志CLI:置IF为0
置1中断标志STI:置IF为1
与外部事件同步的指令
HLT:暂停指令
WAIT:等待指令
ESC:外部协处理器指令前缀
LOCK:总线锁定指令
空操作指令NOP:执行一次NOP占用CPU三个时钟周期,不改变任何寄存器或存储单元内容
5.串操作类指令
6.程序转移类指令
3.指令编码
四种编码格式:
1.双操作数指令编码格式:
2~6个字节,可以包含4个部分,但其中某些部分在一些指令的编码中可以没有:
操作特征部分:OPCODE操作码字段+方向字段d+字/字节字段W
寻址特征部分:MOD+REG+R/M
位移量部分:根据寻址特征中MOD和R/M字段确定的有效地址计算方法,位移量可以是:
没有位移量
1字节位移量disp8
2字节位移量disp16
立即数部分:总是位于指令编码的最后1~2字节
2.单操作数指令编码格式
2~3字节,包括操作特征、寻址特征和位移量三部分
3.与AX或AL有关的指令编码格式:用于隐含指定AX/AL作为一个操作数的双操作数指令
4.其它指令编码格式
如标志位操作指令、堆栈操作指令等,一般只有一个字节
第四章 汇编语言程序格式
1.汇编语言语句种类及其格式
指令语句:每一条指令语句在汇编时都要产生一个可供CPU执行的机器目标代码,又叫可执行语句,
最多可以包含4个字段。
标号字段:可选字段,后面必须有“:”。
标号是一条指令的符号地址,代表了该指令的第一个字节存放地址。一般放在一个程序段或子程序的入口处,控 制程序的执行转到该程序位置。在转移指令或子程序调用指令中,可直接引用这个标号
指令助记符字段
是一条指令的必选项,它表示这条语句要求CPU完成什么具体操作,如MOV、ADD、SHL等。有些指令还可以在指令助记符的前面加上前缀,实现一定的附加操作
操作数字段
注释字段
可选项,该字段以分号“;“开始,它的作用是为阅读程序的人加上一些说明性内容,它不会产生机器目标代码,它不会影响程序和指令的功能。
伪指令语句:又叫命令语句,本身并不产生对应的机器目标代码,仅仅是告诉汇编程序对其后面的指令语句和伪指令语句的操作数应该如何处理;可以包含四个字段:
符号名字段:可选项。根据伪指令的不同,符号名可以是常量名、变量名、过程名、结构名和记录名等等;
符号名后面没有冒号“:”,这是与指令语句的重要区别
伪指令符字段:必选项,规定了汇编程序所要完成的具体操作
操作数字段:该字段是否需要,以及需要几个是由伪指令符字段来决定
注释字段:可选项,作用与指令语句的注释字段相同
标识符:指令语句中的标号和伪指令语句中符号名统称为标识符,由若干个字符构成。
2.汇编语言数据
常用的数据形式有:常数、变量和标号
给变量赋初值4种方式:
-
数值表达式。例如:DATA1 DB 32,30H(DATA1的内容为20H,DATA1+1单元内容为30H)
-
?表达式
不带引号的问号“?”表示可以预置任意内容
-
字符串表达式
对于DB伪指令,字符串为用引号括起来的不超过255个字符,给每一个字符分配一个字节单元。字符串按从左到右,将字符的ASCII编码值以地址递增的排列顺序依次存放
-
DUP表达式:重复数据操作符。
DUP还可以嵌套使用,即表达式2又可以是一个带DUP的表达式
标号:
标号写在一条指令的前面,它就是该指令在内存的存放地址的符号表示,也就是指令地址的别名。
标号主要用在程序中需要改变程序的执行顺序时,用来标记转移的目的地,即作转移指令的操作数。
每个标号具有三属性:
段属性(SEG):即段基值
偏移量属性(OFFSET):即地址的偏移量
距离属性(也叫类型属性):表示该标号可以被段内还是段间的指令调用
NEAR(近):该标号只能作段内转移
FAR(远):该标号可以被非本段的转移和调用指令使用
3.符号定义语句
1.等值语句,格式:符号名 EQU 表达式
功能:用符号名来表示EQU右边的表达式。后面的程序中一旦出现该符号名,汇编程序将把它替换成该表达式。表达式可 以是任何形式,常见以下几种:
常数或数值表达式
地址表达式
变量、寄存器名或指令助记符
2.等号语句,格式:符号名=表达式
功能:与等值语句具有相同的作用,但等号语句可以对一个符号进行多次定义
4.表达式与运算符
操作运算符分为五类:
1.算术运算符:+、—、*、 / 、MOD、SHL、SHR、[ ]
“SHR ”和“SHL”为逻辑移位运算符
下标运算符“[ ]”具有相加的作用。一般使用格式:表达式1 [表达式2]。
作用:将表达式1与表达式2的值相加后形成一个存储器操作数的地址
2.逻辑运算符:NOT、AND、OR和XOR
3.关系运算符:EQ(等于)、NE(不等于)、LT(小于)、 LE(小于等于)、GT(大于)、GE(大于等于)
如果是常量的比较,则按无符号数进行比较;如果是变量的比较,则比较它们的偏移量的大小。其结果只能是“真”或“假”
4.数值返回运算符:将变量或标号的某些特征值或存储单元地址的一部分提取出来
SEG运算符:取变量或标号所在段的段基值
OFFSET运算符:取变量或标号在段内的偏移量
TYPE运算符:取变量或标号的类型属性,并用数字形式表示。对变量来说就是取它的字节长度。
LENGTH运算符:取变量的长度。
SIZE运算符:只能作用于变量,SIZE取值等于LENGTH和TYPE两个运算符返回值的乘积
5.属性修改运算符:对变量、标号或存储器操作数的类型属性进行修改或指定
PTR运算符,格式:类型 PTR 地址表达式
功能:将地址表达式所指定的标号、变量或用其它形式表示的存储器地址的类型属性修改为“类型”所指的值。这种修改是临时的,只在含有该运算符的语句内有效
HIGH/LOW运算符。使用格式:{HIGH|LOW} 表达式
功能:如果表达式为一个常量,则将其分离成高8位和低8位;如果表达式是一个地址(段基值或偏移量)时,则分离出它的高字节和低字节
THIS运算符
功能:一般与等值运算符EQU连用,用来定义一个变量或标号的类型属性。所定义的变量或标号的段基值和偏移量与紧跟其后的变量或标号相同
运算符优先级:
5.程序的段结构
1.段定义伪指令
1.格式
伪指令SEGMENT和ENDS用于定义一个逻辑段。使用时必须配对,分别表示定义的开始与结束
2.定位类型:用于决定段的起始边界,即第一个可存放数据 的位置(不是段基址)
PAGE: 表示该段从一个页面的边界开始
PARA:表示该段从一个小节的边界开始
WORD:表示该段从一个偶数字节地址开始,即段起始 单元地址的最后一位二进制数一定是0
BYTE:表示该段起始单元地址可以是任一地址值
3.组合类型:说明符用来指定段与段之间的连接关系和定位,有六种取值选择
1.若未指定组合类型,表示本段与其它段无连接关系。在装入内存时,本段有自己的物理段,因此有自己的段基址
2.PUBLIC:在满足定位类型的前提下,将与该段同名的段邻接在一起,形成一个新的逻辑段,共用一个段基址。段内的所有偏移量调整为相对于新逻辑段的段基址
3.COMMON: 产生一个覆盖段。
4.STACK:把所有同名段连接成一个连续段,且系统自动对SS段寄存器初始化为该连续段的段基址。并初始化堆栈指针SP。
5.AT表达式:表示本段可定位在表达式所指示的小节边界上。表达式的值也就是段基值
6.MEMORY:表示本段在存储器中应定位在所有其它段之后的最高地址上。如果有多个用MEMORY说明的段,则只处理第一个用MEMORY说明的段。其余的被视为COMMON。
4.类型名:为某一个段或几个相同类型段设定的类型名称
2.段寻址伪指令
ASSUME,作用是告诉汇编程序,在处理源程序时,定义的段与哪个寄存器关联。
一般格式:ASSUME 段寄存器名(CS,DS,ES,SS):段名(段定义伪指令定义的段名),段寄存器名:段名,......
3.段寄存器的装入
初值(段基值)装入需要用程序的方法来实现:
DS和ES的装入:在程序中,使用数据传送语句来实现对DS和ES的装入
SS的装入:
在段定义伪指令的组合类型项中,使用STACK参数,并在段寻址伪指令ASSUME语句中把该段与SS段寄存器关联
如果在段定义伪指令的组合类型中,未使用STACK参数,或者是在程序中要调换到另一个堆栈,这时,可以使用类似于DS和ES的装入方法
CS的装入:
CPU在执行指令之前根据CS和IP的内容来从内存中提取指令,即必须在程序执行之前装入CS和IP的值。因此,CS和IP的初始值就不能用可执行语句来装入
6.过程定义伪指令
在程序设计过程中,常常将具有一定功能的程序段 设计成一个子程序。在MASM宏汇编程序中,用过程(PROCEDURE)来构造子程序。格式如下:
7.当前位置计数器$与定位伪指令ORG
汇编程序在汇编源程序时,每遇到一个逻辑段,就要为其设置一个位置计数器,它用来记录该逻辑段中定义的每一个数据或每一条指令在逻辑段中的相对位置。
格式:ORG 数值表达式
作用:将数值表达式的值赋给当前位置计数器$ 。ORG语句为其后的数据或指令设置起始偏移量。
8.编题伪指令TITLE
格式:TITLE 标题名
作用:给所在程序指定一个标题。以便在列表文件的每一页的第一行都显示这个标题。其中标题是用户任意选用的字符串,字符个数不能超过60。
9.从程序返回操作系统的方法
-
使用程序段前缀PSP(Program Segment Prefix)实现返回
DOS系统将一个.EXE文件(可执行文件)装入内存时,在该文件的前面生成一个程序段前缀PSP,其长度为100H字节。同时让DS和ES都指向PSP的开始,而CS指向该程序的代码段,即第一条可执行指令。
为了使程序执行完后,正确返回DOS,需要做以下三个操作:
将用户程序编制成一个过程,类型为FAR 将PSP的起始逻辑地址压栈,即将INT 20H指令的地址压栈 在用户程序结尾处,使用一条RET指令。执行该指令将使保存在堆栈中的PSP的起始地址弹出到CS和IP中
2.使用DOS系统功能调用实现返回
在程序结束时,使用两条指令:
MOV AH,4CH
INT 21H