Assembly Language Programming 汇编语言程序设计 主讲人 刘雪洁
课程介绍 汇编语言程序设计课程是国家教育部所属高等院校计算机软硬件专业的专业基础课、必修课。 作为一种低级语言,汇编语言是高级语言程序设计的基础,通常被视为微型计算机的又一核心内容。虽然现今大量问题都可应用高级语言编程,但汇编语言是能够利用计算机所有硬件特性并能直接控制硬件的惟一语言,对于直接控制硬件的应用场合或若干实时处理与控制的应用开发项目,汇编语言具有明显的优势。
使用教材 沈美明、温冬婵编著 《IBM-PC汇编语言程序设计(第2版)》 清华大学出版社 2001年 参考: [1]王爽编著《汇编语言》 清华大学出版社 2001年 参考: [1]王爽编著《汇编语言》 清华大学出版社 2003年 [2]钱晓捷编著《汇编语言程序设计》 电子工业出版社 2003年
教学内容 第1章 汇编语言基础知识 第2章 80x86的指令系统 第3章 汇编语言程序格式 第4章 基本汇编语言程序设计 第1章 汇编语言基础知识 第2章 80x86的指令系统 第3章 汇编语言程序格式 第4章 基本汇编语言程序设计 第5章 高级汇编语言程序设计
第1章 汇编语言基础知识 1.1 汇编语言及意义 1.2 数据编码与运算 1.3 数据表示 1.4 80x86CPU和寄存器组 1.1 汇编语言及意义 1.2 数据编码与运算 1.3 数据表示 1.4 80x86CPU和寄存器组 1.5 存储器和端口
1.1 汇编语言及意义 1.1.1机器语言 计算机能够直接识别的数据是由二进制数0和1组成的代码。 机器指令就是用二进制代码组成的指令,一条机器指令控制计算机完成一个基本操作。 用机器语言编写的程序是计算机惟一能够直接识别并执行的程序,而用其他语言编写的程序必须经过翻译才能变换成机器语言程序。 返回本章
1.1.2汇编语言 汇编语言是一种用符号书写的、基本操作与机器指令相对应的、并遵循一定语法规则的计算机语言。 汇编语言是一种符号语言,比机器语言容易理解和掌握,也容易调试和维护。 但对于汇编语言编写的程序必须经过汇编和连接之后,才能在计算机上执行。 返回本节 返回本章
用汇编语言编写的程序称为汇编源程序。采用微机中任何一个文本编辑器编写汇编语言源程序。 汇编程序可将汇编语言源程序翻译成机器代码目标模块。 80x86CPU的汇编程序主要有微软的宏汇编程序MASM。较著名的还有Borland公司的TASM,无实质差别。 返回本节 返回本章
连接程序将汇编后的目标模块转换为可执行程序。连接程序的文件名通常是:LINK.EXE。 源程序 可执行文件 目标模块 文本编辑器 汇编程序 连接程序 返回本节 返回本章
1.1.3高级语言 1.1.4汇编语言特点 高级程序设计语言接近于人类自然语言的语法习惯,与计算机硬件无关,易被用户掌握和使用。 汇编语言程序与处理器指令系统密切相关。 程序员可直接、有效地控制系统硬件。 形成的可执行文件运行速度快、占用主存容量少。 返回本节 返回本章
1.2 数据编码与运算 1.2.1各种进位计数制 (1)十进制计数 十进制数的基数为10,采用数字0、1、2、3、4、5、6、7、8、9共10个数码来计数。每位数字的10k为该位数字的权。 例: (795.412)10 = 7×102+9×101+5×100+4×10-1+1×10-2+2×10-3 返回本章
二进制数的基数为2,只有0、1两个数码,并遵循逢2进1的规则,它的各位权是以2k表示的。 (2)二进制计数 二进制数的基数为2,只有0、1两个数码,并遵循逢2进1的规则,它的各位权是以2k表示的。 例: (11.1001)2 = 1×21+1×20+1×2-1+0×2-2+0×2-3+1×2-4 n位二进制数可以表示2n个数,例如3位二进制数可以表示8个数,即000-111。4位二进制数则表示16个数,即0000-1111。 返回本节 返回本章
十进制数结尾一般用D、二进制数用B、八进制数用O、十六进制数H。如:117D、1010B,67O,1ABH,…。 (3)八进制和十六进制计数 为便于阅读及书写,经常使用八进制数和十六进制数来表示二进制数。八进制的基数为8,数码为0、1 、2、3、4、5、6、7。十六进制数的基数为16,数码为0、1 、2、3、4、5、6、7 、8、9、A、B、C 、D、E、F。按同样的方法,可以容易掌握八进制和十六进制的表示方法。 十进制数结尾一般用D、二进制数用B、八进制数用O、十六进制数H。如:117D、1010B,67O,1ABH,…。 返回本节 返回本章
1.2.2数制的转换 (1)十进制与二、八、十六进制间转换 将十进制数转换成二、八、十六进制数的方法:将数分成整数部分和小数部分,整数部分采用除基取余法,小数部分采用乘基取整法分别进行转换。例:76.425D=1001100.011011B 商 余数 76÷2=38 0 38÷2=19 0 19÷2=9 1 9÷2=4 1 4÷2=2 0 2÷2=1 0 1÷2=0 1 乘积 整数 0.425×2=0.850 0 0.85×2=1.70 1 0.7×2=1.4 1 0.4×2=0.8 0 0.8×2=1.6 1 0.6×2=1.2 1 返回本节 返回本章
例:将十进制数 76.125转换成十六进制数。 商 余数 乘积 整数部分 转换结果为:76.125 = 4C.2H 商 余数 乘积 整数部分 76÷16=4 C(12) 0.125×16=2.0 2 4÷16=0 4 转换结果为:76.125 = 4C.2H 返回本节 返回本章
将二、八、十六进制数转换成十进制数的方法:各位数码与其对应权的积再求和即为该进制数相对应的十进制数。 例: 101.11B = 5.75D B56.D7H=2902.839844D 。 计算过程: 101.11B = 1×22+0×21+1×20+1×2-1+1×2-2 = 4+1+0.5+0.25 = 5.75D B56.D7H = B×162+5×161+6×160+D×16-1+7×16-2 = 2816+80+6+0.8125+0.027344 = 2902.839844 返回本节 返回本章
(2)二进制与八、十六进制间转换 将二进制数转换成八(十六)进制数的方法:一个二制数从小数点向两个方向每3位(4位)划为一组(位数不够补零),然后每组用八(十六)进制数表示就可以了。反之,把八(十六)进制数每一位用3位(4位)二进制数表示,就形成相应的二进制数了。 例:101111010 . 0111001B=17A.72H B56.D7H = 1011 0101 0110 . 1101 0111B 转换过程: 101111010 . 0111001B = 0001 0111 1010 . 0111 0010B = 17A.72H B56.D7H = 1011 0101 0110 . 1101 0111B 返回本节 返回本章
1.2.3数据运算 (1)二进制数运算 二进制加法运算规则:逢2进1。 即 :0+0=0 0+1=1 1+0=1 1+1=0 产生进位1 二进制减法运算规则:借1作2。 即 :0-0=0 0-1=1产生借位1 1-0=1 1-1=0 返回本节 返回本章
加法:当两个一位数之和S小于16时,与十进制同样处理,如果S大于或等于16,则应用S-16及进位1取代S。 二进制乘法运算与十进制乘法运算类似 即 :0×0=0 0×1=0 1×0=0 1×1=1 (2)十六进制运算 加法:当两个一位数之和S小于16时,与十进制同样处理,如果S大于或等于16,则应用S-16及进位1取代S。 减法:与十进制类似,够减时可直接相减,不够减时服从向高位借1为16的规则。 乘法:可用十进制乘法的规则来计算,但结果必须用十六进制数来表示。 返回本节 返回本章
例: 0 5 C 3 H 3 D 2 5 H +3 D 2 5 H - 0 5 C 3 H 4 2 E 8 H 3 7 6 2 H 0 5 C 3 H ×0 0 A 1 H 0 5 C 3 + 3 9 9 E 3 9 F A 3 H 返回本节 返回本章
1.3 数据表示 1.3.1数值数据 数值数据分为有符号数和无符号数。无符号数最高位表示数值,而有符号数最高位表示符号。有符号数有不同的编码方式,常用的是补码。 返回本章
最高位表示符号(正数用0,负数用1),其它位为该数的二进制数值,称为有符号数的原码表示。 (1)原码: 最高位表示符号(正数用0,负数用1),其它位为该数的二进制数值,称为有符号数的原码表示。 【例】 X=45D=00101101B [X]原= 00101101B X=-45D [X]原=10101101B 原码表示简单易懂,但若是两个异号数相加(或两个同号数相减),就要做减法。为了把减法运算转换为加法运算就引进了反码和补码。 返回本节 返回本章
(2)反码: 正数的反码与原码相同,符号位用0表示,数值位不变。负数的反码符号位用1表示, 数值位为原码数值位按位取反形成,即0变1、1变0。 【例】X=45D=00101101B, [X]反=00101101B X=-45D [X]反=11010010B (3)补码: 正数的补码与原码相同,即符号位用0表示,数值位不变。负数的补码为反码加1形成。 【例】X=45D=00101101B [X]补=00101101B X=-45 D [X]补=11010011B 返回本节 返回本章
(4)符号扩展: 在数据处理时,有时需要把8位二进制数扩展成16位二进制数。 当要扩展的数是无符号数时,可在最高位前扩展8个0。 在数据处理时,有时需要把8位二进制数扩展成16位二进制数。 当要扩展的数是无符号数时,可在最高位前扩展8个0。 如果要扩展的数是补码形式的有符号数,那么就要进行符号位的扩展。符号扩展后,其结果仍是该数的补码。 返回本节 返回本章
(5)数据的表示范围和大小 (6)补码的加法和减法 n位二进制数能表示的无符号整数的范围是: 0 ≤I ≤ 2n-1; 补码的特性: [X]补==> [-X]补==> [X]补 补码的加法规则:[X+Y]补=[X]补+[Y]补 补码的减法规则: [X-Y]补=[X]补+[-Y]补 求补 求补 返回本节 返回本章
1.3.2字符数据: (1)ASCII码: 标准ASCII码用7位二进制数编码,共有128个。 计算机存储器基本单位为8位,ASCII码的最高位通常为0,通信时,最高位用作奇偶校验位。 常用字符的ASCII码: 数字'0'~'9':30H~39H 字母'A'~'Z':41H~5AH 字母'a'~'z':61H~7AH 空格:20H 回车CR:0DH 换行LF:0AH 注意回车与换行的差别: CR用来控制光标回到当前行的最左端;LF用来移动光标到下一行,而所在列不变。 返回本节 返回本章
(2) BCD码: 虽然二进制数实现容易,但不符合人们的使用习惯,且书写阅读不方便,所以在计算机输入输出时通常还是采用十进制来表示数,这就需要实现十进制与二进制间的转换。 为了转换方便,常采用二进制编码的十进制,简称为BCD码。 返回本节 返回本章
压缩BCD码:以4个二进制位表示1个十进制位,用0000B~1001B表示0~9。 例如,十进制数6429的压缩BCD码表示为 0110 0100 0010 1001 B(即6429H) 非压缩BCD码:以8个二进制位表示1个十进制位,低4位与压缩BCD码相同,高4位无意义。 例如,十进制数6429的非压缩BCD码表示为 xxxx0110 xxxx0100 xxxx0010 xxxx1001 B 有时,要求非压缩BCD码的高4位为0,这时,6429的非压缩BCD码为06040209H。 返回本节 返回本章
1.4 80x86CPU和寄存器组 计算机硬件: 中央处理单元 CPU(Intel 80x86) 存储器(主存储器) 外部设备(接口电路) 计算机硬件: 中央处理单元 CPU(Intel 80x86) 对汇编语言程序员,最关心其中的寄存器 存储器(主存储器) 呈现给汇编语言程序员的,是存储器地址 外部设备(接口电路) 汇编语言程序员看到的是端口(I/O地址) 返回本章
1.4.1 80x86CPU 计算机执行程序时,首先要将其装入内存,然后由CPU执行程序指令。CPU的作用: 执行算术与逻辑运算, 控制指令的执行。 通常,将Intel公司生产的8086/8088、80286、80386、80486、Pentium、Pentium Pro、Pentium II、Pentium III、Pentium 4 及其兼容的CPU,统称为80x86 CPU或x86 CPU,将基于这些CPU的计算机,称为80x86计算机或x86计算机。 其中,8086CPU是Intel公司于1978年推出的16位微处理器,时钟频率为5MHz,有16位数据信号线,20位地址信号线,可寻址的内存地址空间为1MB。 返回本章
80x86CPU的3种工作模式 1.实模式:与8086兼容的工作模式,只有低20位地址线起作用,仅能寻址第一个1MB的内存空间。MS DOS运行在实模式下。 2.保护模式:32位80x86 CPU的主要工作模式,提供对程序和数据进行安全检查的保护机制。Windows 9x/NT/2000运行在保护模式下。 3.虚拟8086模式:在Windows 9x下,若打开一个MS DOS窗口,运行一个DOS应用程序,那么该程序就运行在虚拟8086模式下。 返回本节 返回本章
1.4.2 80x86寄存器组 8086寄存器组 返回本节 返回本章
1.通用寄存器 (1)数据寄存器 8位数据寄存器8个:AL、AH、BL、BH、CL、CH、DL、DH。 16位数据寄存器4个:AX、BX、CX、DX。 32位数据寄存器4个:EAX、EBX、ECX、EDX。 AL与AH、BL与BH、CL与CH、DL与DH分别对应于AX、BX、CX和DX的低8位与高8位。AX、BX、CX和DX分别对应于EAX、EBX、ECX和EDX的低16位。 返回本节 返回本章
AX寄存器称为累加器。使用频度最高,用于算术、逻辑运算以及与外设传送信息等。 BX寄存器称为基址寄存器。常用于存放存储器地址。 CX寄存器称为计数器。一般作为循环或串操作等指令中的隐含计数器。 DX寄存器称为数据寄存器。常用来存放双字数据的高16位,或存放外设端口地址。 返回本节 返回本章
(2)变址和指针寄存器 变址和指针寄存器包括SI、DI、SP、BP4个16位寄存器和ESI、EDI、ESP、EBP4个32位寄存器,主要用于存放某个存储单元的偏移地址。 其中SI、DI、BP和SP分别对应于ESI、EDI、EBP和ESP的低16位。 。 SI是源变址寄存器,DI是目的变址寄存器,在字符串操作中,SI和DI都具有自动增量或减量的功能。 SP为堆栈指针寄存器,用于存放当前堆栈段中栈顶的偏移地址;BP为基址指针寄存器,用于存放堆栈段中某一存储单元的偏移地址。 返回本节 返回本章
2.段寄存器 80x86CPU的6个16位的段寄存器分别称为代码段寄存器CS,数据段寄存器DS,堆栈段寄存器SS,附加数据段寄存器ES及80386起增加的FS、GS两个段寄存器。 段寄存器用来确定该段在内存中的起始地址。 代码段用来存放程序的指令序列。CS存放代码段的段首址,指令指针寄存器IP指示代码段中指令的偏移地址。 返回本节 返回本章
3.指令指针 8086CPU中的16位指令指针IP,总是保存下一次将要从主存中取出的指令的偏移地址,偏移地址的值为该指令到所在段段首址的字节距离。在目标程序运行时,IP的内容由微处理器硬件自动设置,程序不能直接访问IP,但一些指令却可改变IP的值,如转移指令、子程序调用指令等。 EIP是80386起增加的32位指令寄存器,IP是EIP的低16位。 返回本节 返回本章
4.标志寄存器 状态标志通常由CPU根据指令执行结果自动设置,以反映指令执行结果的特征。 80x86 CPU将状态标志作为条件判断的依据,以控制程序的执行流程。 FLAGS是8086CPU中一个很重要的16位标志寄存器,它包含9个标志位,主要用于保存一条指令执行后,CPU所处状态信息及运算结果的特征。主要包括条件标志和状态控制标志。 OF 11 15 12 DF 10 IF 9 TF 8 SF 7 ZF 6 5 AF 4 3 PF 2 1 CF 返回本节 返回本章
1.条件标志 (1)零标志ZF:若运算结果为0,则ZF = 1,否则ZF = 0。 (2)符号标志SF:若运算结果为负数,则SF=1,否则SF=0。 (3)进位标志CF:若加法时结果最高位向前有进位或减法时最高位向前有借位,则CF = 1,否则CF = 0。 (4)溢出标志OF:若带符号数的运算结果超出了补码表示的范围,则OF = 1,否则OF = 0。 (5)辅助进位标志AF:若加法时结果低4位向前有进位或减法时结果低4位向前有借位,则AF=1,否则AF=0。 (6)奇偶标志PF:若结果操作数中1的个数为偶数,则PF = 1,否则PF = 0。 返回本节 返回本章
深入认识CF和OF CF和OF本质上均表示溢出。 CF表示无符号溢出,即运算结果超出了无符号数的表示范围。对于n位二进制数来说,无符号数表示范围为0~2n-1,例如: n = 8和16时分别为0~255和0~65535。 OF表示带符号溢出,即运算结果超出了带符号数的表示范围。对于n位二进制数来说,带符号数表示范围为-2n-1~2n-1-1,例如,n = 8和16时,分别为-128~127和 -32768~32767。 返回本节 返回本章
(2)中断允许标志IF:当IF=1时,允许CPU响应可屏蔽中断请求,否则关闭中断。 2.状态控制标志 (1)方向标志DF:当DF=1时,每次操作后变址寄存器SI和DI减小,这样使串处理从高地址向低地址方向处理;当DF=0时,则使SI和DI增大。 (2)中断允许标志IF:当IF=1时,允许CPU响应可屏蔽中断请求,否则关闭中断。 (3)追踪标志TF:用于调试时的单步方式操作。当TF=1时,每条指令执行完后产生陷阱,由系统控制计算机;当TF=0时,CPU正常工作,不产生陷阱。 返回本节 返回本章
1.5 存储器和端口 1.5.1 存储器 存储器是计算机的记忆部件,用来存放程序和数据。按所在的位置,存储器可以分成主存储器和辅助存储器。 1.5 存储器和端口 1.5.1 存储器 存储器是计算机的记忆部件,用来存放程序和数据。按所在的位置,存储器可以分成主存储器和辅助存储器。 主存储器存放当前正在执行的程序和使用的数据,CPU可以直接存取,它由半导体存储器芯片构成,其成本高,容量小,但速度快。 辅助存储器可用来长期保存大量程序和数据,CPU需要通过I/O接口访问,它由磁盘或光盘构成,其成本低,容量大,但速度较慢。 返回本章
1.5.2 存储器单元的地址和内容 计算机中信息的单位: 位(Bit):计算机中存储信息的基本单位,可存储一个二进制数:0或1。 1.5.2 存储器单元的地址和内容 计算机中信息的单位: 位(Bit):计算机中存储信息的基本单位,可存储一个二进制数:0或1。 字节(Byte):8位二进制位。位编号从右到左为0~7,第0位为最低位,第7位为最高位。 字(Word):16位二进制位,2个字节。位编号从右到左为0~15,第0位为最低位,第15位为最高位。位0~7为低字节,位8~15为高字节。 双字(Double Word):32位二进制位,4个字节。位编号从右到左为0~31,第0位为最低位,第31位为最高位。位0~15为低字,位16~31为高字。 返回本节 返回本章
存储单元地址 :为了标识和存取每一个存储单元,给每个存储单元规定一个编号,这就是存储单元地址。 在存储器里以字节为单位存储信息,一个字节有惟一的地址。 存储单元的内容 :一个存储单元中存放的信息称为该存储单元的内容。 左图表明了存储器中部分存储单元存放信息情况。从图可看到,地址为34560H的字节的存储单元中的内容是34H,而地址为34561H的字节存储单元中的内容是12H,表示为: (34560H)=34H (34561H)=12H 若从存储单元中取一个词,则高地址内容在高字节。例: (34560H)字=1234H 返回本节 返回本章
1.5.3 物理地址的形成 实模式下允许最大寻址空间为1MB。8086/8088 CPU的地址线是20位的,这样最大可寻址空间应为220=1MB,其物理地址范围从00000H~FFFFFH。而8086CPU寄存器都是16位的。那么,这1MB空间如何用16位寄存器表达呢? 根据要求可把1M字节地址空间划成若干逻辑段。每个逻辑段必须满足两个条件:一是逻辑段的起始地址(简称段首址)必须是16的倍数;二是逻辑段的最大长度为64KB。按照这两个条件,1M字节地址空间最多可划分成64K个逻辑段,最少也要划分成16个逻辑段。逻辑段与逻辑段可以相连,也可以不连,还可以重叠。 返回本节 返回本章
物理地址与逻辑地址 物理地址:内存单元的实际地址,也就是出现在地址总线上的地址。 逻辑地址(分段地址):段地址: 段内偏移地址 段地址表示段在内存中的起始位置,通常被保存在某个段寄存器中。段内偏移地址表示内存单元相对于段起始位置的位移,简称偏移地址,也叫有效地址EA。 段地址与偏移地址都是16位。 系统采用下列方法将逻辑地址自动转换为20位的物理地址: 物理地址 = 段地址 × 16 + 偏移地址 例:逻辑地址为 2E00H:1246H 物理地址=2E00H×16+1246H=2E000H+1246H =2F246H 每个内存单元具有唯一的物理地址,但可由不同的逻辑地址描述。 返回本节 返回本章
1.5.4 端口 端口就是指I/O地址,是微机系统对I/O接口电路中与程序设计有关的寄存器的编号 系统实际上就是通过这些端口与外设进行通讯的 1.5.4 端口 对程序员来说,I/O接口电路由接口寄存器组成,为了区别它们,各个寄存器进行了编号,形成I/O地址。 端口就是指I/O地址,是微机系统对I/O接口电路中与程序设计有关的寄存器的编号 系统实际上就是通过这些端口与外设进行通讯的 通常采用十六进制数来表达端口 Intel 8086支持64K个8位端口 其I/O地址可以表示为:0000H ~ FFFFH 返回本节 返回本章
本章小结 汇编语言是机器语言的符号表示,与机器语言无本质区别。 计算机系统使用2进制表示数据。为了描述方便,书写时常采用16进制形式。 数值数据分无符号数和有符号数两种。有符号数具有原码、反码和补码三种编码。以补码表示的带符号数在基于不同位数时,其二进制形式可能完全不同。 字符数据常用编码有ASCII码和BCD码。 返回本章
80x86计算机由CPU、内存和I/O子系统三部分组成,各部分之间由系统总线相连。 字的存储采取“低字节在低地址,高字节在高地址,字的地址由低地址表示”的方式,双字也类似。 要正确理解内存单元的地址和值,地址表示位置,值是相应位置处的内容。同一地址既可以看作字节单元地址,也可以看作字甚至双字单元地址,取决于具体的使用方式。 返回本章
8位通用寄存器8个:AH、AL、BH、BL、CH、CL、DH、DL。 16位通用寄存器8个:AX、BX、CX、DX、SI、DI、BP、SP。 80x86 CPU具有8位、16位和32位寄存器。 8位通用寄存器8个:AH、AL、BH、BL、CH、CL、DH、DL。 16位通用寄存器8个:AX、BX、CX、DX、SI、DI、BP、SP。 32位通用寄存器8个:EAX、EBX、ECX、EDX、ESI、EDI、EBP、ESP。 16位段寄存器6个:CS、DS、SS、ES、FS、GS。 32位/16位指令指针1个:EIP/IP。 32位/16位标志寄存器1个:EFLAGS/FLAGS。 其中,32位寄存器是80386 CPU开始引入的。 返回本章
80x86 CPU有3种工作模式:实模式、保护模式和虚拟8086模式。 在实模式下,段地址和偏移地址均为16位。20位物理地址由16位段地址左移4位加16位偏移地址得到,只能寻址1MB的内存空间,且每段≤64KB。 在实模式、32位CPU下的程序可以使用32位寄存器和32位操作数,但采用32位寄存器表示偏移地址时,只使用低16位,高16位为0。CS:IP总是指向下一条要执行的指令,EIP的高16位为0。SS:SP指向堆栈段的栈顶,ESP的高16位为0。 状态标志是CPU进行条件判断和控制程序执行流程的依据,最常用的是4个:CF、OF、SF和ZF。其中,CF表示无符号溢出,OF表示带符号溢出。 返回本章