Presentation is loading. Please wait.

Presentation is loading. Please wait.

第四章 80x86汇编语言程序设计 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第五节 编写完整的汇编语言程序 第六节 汇编语言程序设计.

Similar presentations


Presentation on theme: "第四章 80x86汇编语言程序设计 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第五节 编写完整的汇编语言程序 第六节 汇编语言程序设计."— Presentation transcript:

1

2

3

4 第四章 80x86汇编语言程序设计 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令
第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第五节 编写完整的汇编语言程序 第六节 汇编语言程序设计

5 助记符——用便于记忆的英语单词表示的指令操作码。它反映了指令的功能和主要特征,便于人们理解和记忆。
第一节 汇编语言概述 机器语言——二进制数形式的指令和数据。 B0 64 是什么意思?这就是机器语言。既不直观,又不易理解和记忆. MOV AL,64H ;很容易记忆理解,这就是助记符。 助记符——用便于记忆的英语单词表示的指令操作码。它反映了指令的功能和主要特征,便于人们理解和记忆。

6 汇编语言——指令助记符,符号地址,标号,伪指令等语言元素的集合以及这些元素使用的规则。 用汇编语言编写的程序叫汇编语言源程序。
指令除了操作码以外,还有一个操作数问题。 操作数可能放在存储器中,这就涉及操作数的地址。程序中遇到转移指令或调用指令,也需要知道转移地址,若采用具体地址就很不方便,一旦有错,改动也很麻烦。于是人们采用标号或符号来代替地址,例: LP1: mov ax,VAR loop LP1 汇编语言——指令助记符,符号地址,标号,伪指令等语言元素的集合以及这些元素使用的规则。 用汇编语言编写的程序叫汇编语言源程序。

7 高级语言 面向过程的语言,如C、C++、BASIC、PASCAL等 优点:更接近人类语言的语法习惯,易于掌握,便于建立数学模型和实现复杂算法
缺点:与机器语言无明显对应关系,因此编译出来的机器语言程序效率相对较低,占用内存多,执行时间长。

8 汇编程序 汇编源程序需翻译成机器语言,变成可执行文件,机器才能执行,这个翻译过程叫汇编。——高级语言中称该过程为“解释”或“编译”。执行翻译的程序称为“汇编程序”。 汇编语言源程序 汇编程序 机器语言目标程序 源程序的编译程序

9 汇编语言程序设计与执行过程 输入汇编语言源程序 源文件 .ASM 汇编(编译) 目标文件 .OBJ 链接 可执行文件 .EXE
调试 最终程序 编辑器: EDIT.exe 编程序: MASM.exe 连接程序:LINK.exe 调试程序:DEBUG.exe

10 一个简单的8086系统下的汇编语言程序: 数据段 代码段
DATA SEGMENT STRING DB ‘HELLO WORLD!’, 0DH, 0AH, ‘$’ DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA BEGIN: MOV AX, DATA MOV DS, AX ;初始化数据段的段地址 MOV AH, 09H LEA DX, STRING;输出字符串 INT 21H MOV AH, 4CH INT 21H;调用4CH号系统功能返回DOS CODE ENDS END BEGIN 数据段 代码段

11 第二节 汇编语言语句的组成 一、字符集 汇编语言程序的语句中包含的元素 四、表达式及运算符 二、保留字与标识符 三、常量、变量与标号

12 一、字符集 允许使用的字符: 注意: 字母,包括大写字母A~Z和小写字母a~z; 数字,包括0~9;
特殊字符,包括:+ - * / =()[ ] < > ; , ‘ “ . — $ & 及空格、制表符、回车、换行等。 注意: 除了字符串,字母都是不区分大小写 一系列相连的空格、制表符效果相当于一个空格 一系列相连的回车换行相当于一次回车换行 分号“;”后一直到行尾的内容都是注释 字符“&”若用于某行的开头,则表示该行是上一行的续行

13 二、保留字与标识符 1、保留字 在汇编语言中有特定意义的词,可分为: 指令助记符及指令前缀 如:MOV、ADD、REP等 寄存器名
如:AX、EBX、CL等 伪指令助记符 如: DB、SEGMENT等 其他保留字,包括运算符、操作符等 如: EQ、LT、OFFSET、SEG等

14 2、标识符 标识符是程序员自己起的名字,如变量名、标号、段名、过程名等 标识符的命名规则:
标识符必须由字母、数字和几个特殊字符(包括 $ ? :)组成,而且第一个字符不能是数字(否则可能与16进制的数字混淆) 标识符不能与某个保留字相同,以免混淆 尽量用有意义的英文单词或缩写来命名,以增加程序的可读性

15 三、常量、变量与标号 1、常量 数字常量 二进制:以B结尾,如10101010B 八进制:以Q结尾,如123Q,67Q
十进制:以D结尾,“D”可省略,如1234D,5678 十六进制:以H结尾,A~F开头的数须在前面加“0” 如:1234H,0FFFFH 字符串常量 用单引号或双引号引起来的一个或多个ASCII字符 每个字符的值等于其ASCII码值 例:‘A’=41H一个字节,‘12’=31H、32H两个字节

16 2、变量 变量是存放在存储器中的操作数 可通过变量的名字来访问变量 变量具有三个属性: 段属性,即变量所在的段的基地址;
偏移量属性,即变量相对于段的起始地址的偏移量; 类型属性,包括BYTE(字节)、WORD(字)、DWORD(双字)

17 3、标号 标号是一条指令性语句的起始地址 标号具有三个属性: 段属性,即标号所在的段的基地址;
偏移量属性,即标号相对于段的起始地址的偏移量; 类型属性,包括NEAR(近程,即段内)、FAR(远程,即段间)

18 四、表达式及运算符 由常量、变量、标号和一些运算符、操作符构成的式子 表达式的值在汇编的过程中就已经被汇编程序计算出来 运算符的分类:
算术运算符 逻辑运算符 关系运算符 属性运算符 数值返回操作符

19 1、算术运算符 五种算术运算: 合法地址表达式:地址-地址(处在同个段中);地址±常数
加:+、 减:-、 乘:*、 除:/、 模:MOD 合法地址表达式:地址-地址(处在同个段中);地址±常数 ADDR1-ADDR2(假设两个地址处在同个段中) ADDR1+1 ADDR2-2 非法地址表达式:地址+地址;地址*地址;地址/地址;常量-地址;地址-地址(处在不同段中) ADDR1+ADDR2 ADDR1*ADDR2 ADDR1/2 100-ADDR1 SEG1_A-SEG2_B (假设两个地址处在不同段中)

20 2、逻辑运算符 五种逻辑运算: 只用于数字表达式中 例: 与AND、或OR、异或XOR、非NOT、逻辑左移SHL、逻辑右移SHR
MOV AL, B AND B ;AL← B MOV AX, B XOR B ;AX← B

21 3、关系运算符 六种关系运算符: 运算结果: EQ(Equal,相等) NE(Not Equal,不等) LT(Less Than,小于)
LE(Less than or Equal,小于或等于) GT(Great Than,大于) GE(Great than or Equal,大于或等于) 运算结果: 关系为真,则运算结果为0FFFFH 关系为假,则运算结果为0 如:MOV BX,1 EQ 2; 结果 BX=0 MOV AX,(3 LT 4) AND 1;结果 AX=1

22 (1)型重新指定操作符PTR 4、属性运算符 功能: 格式: 例: 类型 PTR 表达式 VAR_W DW 1234H
临时指定或修改存储器操作数的数据类型属性或地址类型属性 格式: 类型 PTR 表达式 例: VAR_W DW 1234H MOV AX,VAR_W ;AX←1234H MOV AL,BYTE PTR VAR_W ;AL←34H

23 PTR与EQU连用 作用: 定义与表达式类型不同的新变量名或新标号,但不分配新的存储单元 例: 数据段定义: 代码段:
DATA_B DB ,2,3,4 DATA_W EQU WORD PTR DATA_B 代码段: MOV AL,DATA_B ;AL←1 MOV AX,WORD PTR DATA_B ;AX←0201H MOV AX,DATA_W ;AX←0201H (第2、3条指令等价)

24 (2)类型指定操作符THIS 功能: 例1: 例2: 指定或说明变量或标号的类型 DATA_W EQU THIS WORD
DATA_B DB 1,2,3,4 MOV AL,DATA_B ;AL←1 MOV AX,WORD PTR DATA_B ;AX←0201H MOV AX,DATA_W ;AX←0201H 例2: ADDR_F EQU THIS FAR ADDR_N: MOV AX,1 JMP ADDR_F ;等价于:JMP FAR PTR ADDR_N

25 (3)短转移操作符SHORT 一般用在JMP指令 告诉汇编程序该JMP指令是一个短程转移指令 功能: 例: JMP SHORT LAB ……

26 (1)SEG、OFFSET 5、数值返回操作符 功能: 例如,对于代码段中的一条指令: SEG操作符用于求一个标号或变量所在段的基地址
2000H:1234H ADDR: INC CX ;段地址=2000H,偏移量=1234H 则有: MOV AX,SEG ADDR ;AX←2000H MOV AX,OFFSET ADDR ;AX←1234H ;与指令 “LEA AX,ADDR” 等价

27 (2)TYPE、LENGTH、SIZE 功能: TYPE:求变量的数值类型属性,即变量具有的字节数
BYTE:返回1;WORD:返回2;DWORD :返回4; NEAR:返回0FFH(-1);FAR:返回0FEH(-2) LENGTH:求变量所占用的内存单元数 用于由重复操作符DUP()定义的存储器变量 对于其他变量,LENGTH的返回值都是1 SIZE:计算变量所占存储器的总字节数 关系: SIZE = LENGTH × TYPE

28 例: DATA1 DW 1234H DATA2 DB ‘HELLO’ DATA3 DD 100 DUP(0);表示定义100个值为0的双字
MOV AL,TYPE DATA1 ;AL←2 MOV AL,TYPE DATA2 ;AL←1 MOV AL,TYPE DATA3 ;AL←4 MOV BL,LENGTH DATA1 ;BL←1 MOV BL,LENGTH DATA2 ;BL←1 MOV BL,LENGTH DATA3 ;BL←100 MOV CL,SIZE DATA1 ;CL←2×1=2 MOV CL,SIZE DATA2 ;CL←1×1=1 MOV CL,SIZE DATA3 ;CL←4×100=400

29 6、运算符的优先级 表达式计算顺序: 优先级顺序: 先处理优先级别高的运算符 对于优先级相等的运算符,则按从左至右的顺序进行处理
()、[](优先级最高) LENGTH、SIZE PTR、THIS、SEG、OFFSET、TYPE HIGH、LOW *、/、MOD、SHL、SHR +、- EQ、NE、LT、LE、GT、GE NOT AND OR、XOR SHORT(优先级最低)

30 第三节 汇编语言的语句 汇编语言由指令性语句和指示性语句组成
第三节 汇编语言的语句 汇编语言由指令性语句和指示性语句组成 指令性语句由CPU执行,每一条指令性语句都有一条机器码指令与其对应; 指示性语句由汇编程序执行。它指出汇编程序应如何对源程序进行汇编,如何定义变量、分配存储单元以及指示程序开始和结束等。指示性语句无机器码指令与其相对应。 指令性语句汇编时生成机器码; 指示性语句汇编时不生成机器码。

31 第三节 汇编语言的语句 一、指示性语句 格式([]里的内容可选): 名字:变量名、段名等,与指令地址无关,后面不能加冒号
第三节 汇编语言的语句 一、指示性语句 格式([]里的内容可选): [名字] 伪指令符 操作数,操作数,…… [;注释] 名字:变量名、段名等,与指令地址无关,后面不能加冒号 伪指令符:指定汇编程序要完成的具体操作 操作数:常量、变量或表达式等 注释:说明、解释当前语句的作用 31

32 1、数据定义伪指令 功能: 格式: 六种数据定义伪指令: 为变量分配存储空间 DB(字节定义):每个操作数占1个字节
[变量名] 伪指令符 操作数,操作数,…… [;注释] 六种数据定义伪指令: DB(字节定义):每个操作数占1个字节 DW(字定义):每个操作数占1个字,即2个字节 DD(双字定义):每个操作数的长度为双字,即4个字节

33 例: 可同时定义多个数据: NUM DW 12H,-1 ;定义2个字 STRING DB ‘HELLO’,0DH,0AH;定义字符串
省略变量名: BUF DB ,10,100 DB ;省略变量名 ;但该数据仍可通过“BUF+3”访问 无初始化数据定义:用问号“?”代替操作数 BUFFER DB ,?,?,? ;定义4个字节 ;其中后3个字节不初始化

34 DUP操作符: 格式: 重复的次数 DUP(重复的内容) 例: ARRAY DB 3 DUP(1,2)
BUF_W DW 100 DUP(?) ;定义100个字,但不初始化 DUP的嵌套使用: ARRAY2 DB 2 DUP(1,3 DUP(0)) ;等价于:ARRAY2 DB 1,0,0,0,1,0,0,0

35 只能用DW、DD定义 DW:变量/标号的偏移量 DD:变量/标号的段地址和偏移量 例: 地址表达式作为操作数:
DATA1 DW ADDR1+1 ;把ADDR1偏移量加1后存放到DATA1对应的存储单元中 DATA2 DD DATA1 ;把DATA1的偏移量和段地址存放到DATA2对应的存储单 元中,其中偏移量放低地址,段地址放高地址。

36 地址计数器“$” “$”:表示到目前为止该段已经使用的地址空间 例1: 设VAR1地址偏移量为1000H,则: VAR1 DB 100H DUP (?) 之后,$=1100H,因此: ADDR1 DW $ 等价于“ADDR1 DW 1100H”,也等价于“ADDR1 DW ADDR1” 例2: STRING DB ‘ABC’ LEN DW $-STRING ;LEN的值为STRING的长度

37 2、符号定义伪指令 (1)等价伪指令EQU 格式: 功能: 例: 符号名 EQU 表达式 为常量、表达式及其他各种符号定义一个别名
NUM EQU ;给数值定义符号名 NUM2 EQU NUM+10 ;给12+10=22定义符号名 ADDR EQU DS:[BX+SI] ;给寻址表达式定义符号名 COUNT EQU CX ;给寄存器CX定义符号名 CLEAR EQU XOR AX,AX ;给指令定义符号名

38 (2)解除伪指令PURGE 格式: 作用: 例: PURGE 符号名,符号名,……
EQU伪指令不能直接对一个符号名重定义,必须先用PURGE解除 例: COUNT EQU CX PURGE COUNT COUNT EQU CL

39 (3)等号“=”伪指令 格式: 功能: 例: 符号名 = 表达式 为常量、表达式及其他各种符号定义一个等价的符号名
符号名 = 表达式 功能: 为常量、表达式及其他各种符号定义一个等价的符号名 允许对符号名多次重复定义,且以最后一次定义的值为准 例: CONST = ;给数值1定义符号名CONST ADDR = [BP+DI] ;给寻址表达式定义符号名ADDR CONST = ;重定义CONST

40 3、段定义伪指令 格式: 段名 SEGMENT [定位方式][组合方式][使用类型][‘类名’] 功能:定义一个段 例:
…… ;段中的内容 段名 ENDS 功能:定义一个段 例: DATA SEGMENT VAR DB ? DATA ENDS 得到段地址的两种方法: MOV AX,DATA MOV AX,SEG VAR

41 (1)定位方式 作用: 分类: 设置该段在存储器中的起始边界 BYTE:可从任意的绝对地址开始,如12345H。
WORD:可从偶地址开始。如12346H。 DWORD:可以任何一个双字的边界开始,如12348H。 PARA(缺省方式):必须从存储器的16字节的边界开始,如12340H(最后一位为0)。 PAGE:起始地址必须能被256整除,如12300H。

42 (2)类名 如:在模块1中有段定义: seg1 SEGMENT PARA STACK ‘stack’ … seg1 ENDS
用单引号括起来的字符串 连接定位时,具有相同类名的逻辑段会被组合在一起 如:在模块1中有段定义: seg1 SEGMENT PARA STACK ‘stack’ seg1 ENDS 在模块2中有段定义: seg2 SEGMENT PARA STACK ‘stack’ seg2 ENDS 则连接时这两个段被安排在一起。

43 (3)使用类型(386以上) USE16:缺省类型,表示该段采用16位寻址方式,段基址和段内偏移量都是16位 USE32:表示该段采用32位寻址方式,段选择子为16位,段内偏移量则是32位

44 (4)组合方式 作用: 分类: 指定同类名段的组合方法 PRIVATE(缺省方式):不组合 PUBLIC:同类名段按照前后次序连接在一起
COMMON:与其他模块中的同类名段有相同的起始物理地址 STACK:与其他模块中的同类名段用覆盖的方式连接,从高地址开始覆盖 MEMORY:该段必须放在同类名的各个段中的最后 AT表达式:直接指定该段的段地址

45 4、假定伪指令ASSUME 格式: 功能: 例: ASSUME 段寄存器:段名[,段寄存器:段名,……] 告诉汇编程序段与段寄存器的对应关系
DATA SEGMENT VAR1 DB ? DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA BEGIN: …… ASSUME指令:假定CS为代码段,DS为数据段

46 5、地址对准伪指令 ORG 格式: 功能: 例: ORG 数值表达式 用于指定下一个指令或数据在段内的起始地址 LAB1: PUSH AX
ORG 2000H LAB2: MOV AL,34 则LAB2的地址偏移量为2000H。

47 6、过程定义伪指令PROC、ENDP 功能: 格式: 过程属性: 定义一个过程 NEAR:缺省属性,表示段内调用/返回
…… 返回指令RET 过程名 ENDP 过程属性: NEAR:缺省属性,表示段内调用/返回 FAR:表示段间调用/返回

48 7、源程序结束伪指令END 格式: 功能: 例: END 标号 标号的地址必须是程序的入口地址,即第一条可执行语句
告诉汇编程序,源程序到此已经结束 告诉汇编程序,源程序的入口地址是多少 例: CODE SEGMENT ASSUME CS:CODE BEGIN: MOV AX,0 ;第一条指令语句 …… CODE ENDS END BEGIN ;源程序到此为止

49 8、高级数据结构定义伪指令 (1)结构类型数据定义伪指令STRUC/ENDS 结构的定义: 结构名 STRUC
…… ;DB、DW之类的数据定义伪指令语句序列 结构名 ENDS 例: DATA STRUC X DW 0 Y DB 1 Z DD 2 DATA ENDS 结构定义时并没有分配存储空间

50 结构变量的申请与赋初值 结构的访问 结构变量名 结构名 <初始值表> 例: NEW _DATA DATA <,,0>
结构变量名 结构名 <初始值表> 例: NEW _DATA DATA <,,0> ;申请结构变量“NEW _DATA”,其中X=0,Y=1,Z=0 ;缺省的初始值表示使用定义时的预设值 结构的访问 结构变量名.字段名 MOV AX,NEW_DATA.X MOV BL, NEW_DATA.Y

51 (2)记录定义伪指令RECORD 记录的定义 记录名 RECORD 字段说明,字段说明…… 其中,字段说明的格式是:
字段名:宽度 [=预赋值] 例: REC RECORD A:8=12H, B:5=10, C:3 定义了一个字,其中: A占高8位,预赋值= B B占接下来5位,预赋值=10 C占低3位,预赋值为空

52 00010010B 00001B 010B 记录变量的的申请与赋初值 格式: 记录变量名 记录名 <初始值表> 例:
记录变量名 记录名 <初始值表> 例: REC_VAR REC <,1,2> 申请了一个变量REC_VAR,其值为: B B B 预赋值12H 初始化为 初始化为2

53 记录的访问 WIDTH操作符: 求记录或记录中某个字段的宽度(即位数)。格式: WIDTH 记录名或记录字段名 记录字段名:
求该字段的最低位右移到所在记录最右边所需的移位次数 MASK操作符: 返回一个8位或16位二进制数,这个数中,对应于指定字段的各位均是1,其余各位均是0。格式: MASK 记录字段名 例: MOV AX,REC_VAR ;AX← B MOV BL,WIDTH REC_VAR ;BL←REC_VAR的总宽度16 MOV BH,WIDTH A ;BH←字段A的宽度8 MOV CL,B ;CL←3 MOV DX,MASK C ;DX← B

54 二、指令性语句 NIL指令 格式: NIL指令并不属于80x86的指令系统 只用于宏汇编中 作用:保留一个空行 例:
[标号:] 指令助记符 操作数,操作数,…… [;注释] NIL指令 NIL指令并不属于80x86的指令系统 只用于宏汇编中 作用:保留一个空行 例: L: NIL ;留下一个空行,方便以后对程序的修改 LOOP L 等价于:L:LOOP L

55 DOS系统功能调用介绍 系统功能调用——由OS提供的一组实现特殊功能的子程序供程序员在程序中调用,以减轻编程工作量。
系统功能调用有两种,一种称为DOS功能调用,另一种称为BIOS功能调用。 用户程序在调用这些系统服务程序时,不是用CALL命令,而是采用软中断指令INT n来实现。 在DOS系统中,功能调用都是用软中断指令INT 21H来实现的。

56 格式: 将调用功能所需的入口参数存入指定的寄存器或存储单元中; 在寄存器AH中存放所要调用功能的功能号; 执行INT 21H指令,转入中断子程序; 中断子程序运行完后,从指定的寄存器或存储单元中取得出口参数。

57 (1)单字符显示(功能号:02H) (2)单字符输入(功能号:01H、07H) 功能:将指定的字符送到显示器显示 例:
MOV DL,‘A’ ;入口参数,DL存放字符的ASCII码 MOV AH,02H ;02H号功能调用 INT 21H ;显示字符‘A’ (2)单字符输入(功能号:01H、07H) 功能:从键盘输入字符→AL MOV AH,01H;01H号键盘输入功能调用 INT 21H ;AL←输入字符的ASCII码,并显示字符 07H号功能调用与01H号相似,但输入的字符没有在屏幕上显示

58 (3)检测键盘状态(功能号:0BH) 功能: RUN:…… ;循环运行的程序段 …… MOV AH,0BH ;0BH号功能调用
检测当前时刻键盘是否有键按下。如果有,则出口参数AL=0FFH,否则AL=0。该功能不清除输入缓冲。 例:循环运行程序段,直到有按键按下为止 RUN:…… ;循环运行的程序段 …… MOV AH,0BH ;0BH号功能调用 INT H ;检测键盘状态 CMP AL,0 JZ RUN ;AL=0表示没有键按下 MOV AH,01H ;没有清除缓冲,仍可读到按键 INT H

59 (4)直接控制台I/O(功能号:06H) 功能: 输入 / 输出字符:
入口参数DL=0FFH:检测当前时刻键盘是否有键按下。如果有,则出口参数AL=输入的字符,ZF=0,清除输入缓冲区;如果没有,则ZF=1。 入口参数DL≠0FFH:将DL中的ASCII码送显示器上显示 例:循环运行程序段,直到有按键按下为止 RUN:…… ;循环运行的程序段 …… MOV AH,06H ;06H号功能调用 MOV DL,0FFH ;DL=0FFH,输入功能调用 INT H ;检测键盘状态 JZ RUN

60 (5)字符串显示(功能号:09H) 功能: 字符串的首地址→DS:DX中, 字符串一定要以字符‘$’作为结尾标志 例:
将数据段中的字符串输出到屏幕上 字符串的首地址→DS:DX中, 字符串一定要以字符‘$’作为结尾标志 例: DATA SEGMENT STRING DB ‘HELLO’,0DH,0AH,‘$’;需以‘$’结尾 DATA ENDS 代码段: MOV AX,DATA MOV DS,AX ;DS←字符串所在段的段地址 LEA DX,STRING ;DX←字符串首地址的偏移量 MOV AH,09H ;09H号功能调用 INT 21H ;在屏幕上显示“HELLO”

61 (6)字符串输入(功能号:0AH) 功能:字符串输入,回车键结束 入口参数: DS:DX:缓冲区首地址 (DS:DX):允许输入的最多字符数
例: BUF DB 10H,100 DUP(?);输入字符数不超过16 MOV AX,DATA MOV DS,AX ;DS←缓冲区所在段的段地址 LEA DX,BUF ;DX←缓冲区首地址的偏移量 MOV AH,0AH ;0AH号功能调用 INT H ;输入字符串 若输入“123”,则BUF中的内容为: 10H,03H(输入3个字符),31H,32H,33H,0DH(回车)

62 (7)打印输出(功能号:05H) (8)结束调用(功能号:4CH) 功能:将DL寄存器中的字符送打印机打印 例:
MOV DL,‘A’ ;需打印的字符‘A’ MOV AH,05H ;05H号功能调用 INT 21H ;送打印机打印 (8)结束调用(功能号:4CH) 功能:终止当前程序,并返回到DOS中 MOV AH,4CH INT 21H

63 第四节 宏汇编指令 一、宏操作伪指令 宏定义伪指令 MACRO、ENDM 取消宏定义伪指令 PURGE
第四节 宏汇编指令 一、宏操作伪指令 宏定义伪指令 MACRO、ENDM 取消宏定义伪指令 PURGE 重复伪指令 REPT、IRP、IRPC 局部符号伪指令 LOCAL

64 1、宏定义伪指令MACRO、ENDM 格式: 例1: 宏名 MACRO [形式参数1,形式参数2,……] …… ;宏体
…… ;宏体 ENDM ;宏定义结束 例1: OUTPUT MACRO MOV AH,02H INT 21H ENDM 则: OUTPUT 等价于 “MOV AH,02H,INT 21H”

65 例2: OUTPUT MACRO ASC ;“ASC”为形式参数 MOV DL,ASC MOV AH,02H INT 21H ENDM 则:
OUTPUT 30H 等价于: MOV DL,30H

66 2、取消宏定义伪指令PURGE 功能: 使用MACRO定义的宏,如果不再需要,就可以用PURGE来注销 格式:
例: PURGE OUTPUT

67 3、重复伪指令REPT、IRP、IRPC 格式: 功能: 例如,下面的宏能将AL中的值逻辑左移4位: REPT REPT 表达式
…… ;宏体 ENDM 功能: 重复执行宏体中的语句,重复次数为表达式的值。 例如,下面的宏能将AL中的值逻辑左移4位: REPT 4 SHL AL,1

68 例,把AX、BX、CX、DX都压入栈中:
IRP 格式: IRP 形式参量,<参数,参数,……> …… ;宏体 ENDM 功能: 重复执行宏体,重复的次数是由参数的个数决定 例,把AX、BX、CX、DX都压入栈中: IRP REG,<AX,BX,CX,DX> PUSH REG

69 格式: 功能: 例如: IRPC IRPC 形式参量,字符串 …… ;宏体 ENDM
…… ;宏体 ENDM 功能: 重复执行宏体,其参数列表是字符串,一个字符为一个参数 例如: IRPC NUM,1234 ;“1234”表示4个参数1、2、3、4 DB NUM 等效于:DB 1,2,3,4

70 4、局部符号伪指令LOCAL 格式: 功能: 例: 正确: 错误: IRP REG,<AX,BX>
将宏中的标号定义为局部符号,避免重复 例: 正确: IRP REG,<AX,BX> LOCAL LAB LAB: PUSH REG ENDM 展开后: ??0000: PUSH AX ??0001: PUSH BX 错误: IRP REG,<AX,BX> LAB: PUSH REG ENDM 展开后: LAB: PUSH AX LAB: PUSH BX (LAB重复使用,出错)

71 二、条件汇编 格式: 功能: IFxx <条件表达式> …… ;条件块1 [ELSE] …… ;条件块2 ENDIF
…… ;条件块1 [ELSE] …… ;条件块2 ENDIF 功能: 根据某个表达式的真假,决定是否对指定的程序段进行编译

72 第五节 编写完整的汇编语言程序 一、汇编语言程序与MS-DOS 二、一般的汇编语言程序的整体框架 三、模块化程序设计的思想

73 一、汇编语言程序与MS-DOS 1、DOS的装入功能 确定用于存放程序的内存地址空间
建立程序段前缀PSP(Program Segment Prefix) 100H个字节,存放程序有关信息及进程间的控制信息 最开始的两个字节是一条INT 20H软中断指令 在PSP后装入可执行程序: 数据段 附加段 代码段 堆栈段

74 初始化各个相关寄存器的值: DS、ES:PSP所在段的段地址 CS、IP:程序的入口地址 SS初始化为堆栈段的段地址 SP指向堆栈段的栈底
入口地址 = 第一条可执行语句的段地址和偏移量 这个地址是从END语句中标号的地址属性得到的 SS初始化为堆栈段的段地址 SP指向堆栈段的栈底

75 2、DOS的返回 方法一: 执行PSP中的“INT 20H”指令: CS←PSP的段地址 IP←0 具体过程: 程序开头:
PUSH DS ;开始时(DS)=PSP的段地址 MOV AX,0 PUSH AX ;“0”入栈 程序过程,要求PUSH与POP配对 程序结束: RET ;CS←PSP的段地址,IP←0

76 例: CODE SEGMENT ASSUME CS:CODE MAIN PROC FAR BEGIN: PUSH DS ;PSP的段地址入栈
MOV AX,0 ;INT 20H的偏移量为0 PUSH AX ;把偏移量入栈 …… RET ;IP←0,CS←PSP段地址 MAIN ENDP CODE ENDS END BEGIN

77 方法二: 调用DOS系统的4CH 功能,实现DOS返回: MOV AH,4CH INT 21H 例: CODE SEGMENT
ASSUME CS:CODE BEGIN: …… …… MOV AH,4CH ;返回DOS INT 21H CODE ENDS END BEGIN

78 二、一般的汇编语言程序的整体框架 数据段、附加段 注释 堆栈段 END伪指令 ASSUME伪指令 代码段

79 源程序结构框架 框架一: 数据段 堆栈段 DATA SEGMENT ;数据段 …… ;定义变量、缓冲区等 DATA ENDS
…… ;定义变量、缓冲区等 DATA ENDS STACK SEGMENT PARA STACK ‘STACK’ ;堆栈段部分 DB XXXX DUP(?) ;定义堆栈的长度 STACK ENDS CODE SEGMENT ;代码段部分 ASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA MAIN PROC FAR BEGIN: PUSH DS MOV AX,0 ; 为RET提供转移地址 PUSH AX 数据段 堆栈段

80 MOV AX,DATA MOV DS,AX ;初始化段寄存器DS、ES MOV ES,AX …… ;程序部分 RET ;返回DOS MAIN ENDP PROC_1 PROC NEAR/FAR …… ;定义其他过程 RET PROC_1 ENDP CODE ENDS END MAIN

81 框架二: 采用“4CH”功能返回:(代码段部分) CODE SEGMENT ;代码段 ASSUME CS:CODE,DS:DATA,
& SS:STACK,ES:DATA BEGIN: MOV AX,DATA MOV DS,AX ;初始化DS、ES MOV ES,AX …… ;程序部分 MOV AH,4CH ;4CH号功能调用 INT 21H ;返回DOS CODE ENDS END BEGIN

82 三、模块化程序设计的思想 1、模块命名伪指令NAME、TITLE 2、逻辑段与物理段 格式: 作用: 为模块命名,指示给连接程序进行连接用
编译连接时,同类逻辑段将组合成一个大的物理段

83 3、同类名的组合方式 PRIVATE(缺省方式):不组合 PUBLIC:同类名段按照前后次序连接在一起
COMMON:与其他模块中的同类名段有相同的起始物理地址 STACK:与其他模块中的同类名段用覆盖的方式连接,从高地址开始覆盖 MEMORY:该段必须放在同类名的各个段中的最后 AT表达式:直接指定该段的段地址

84 4、模块之间的通信 格式: 功能: PUBLIC与EXTRN: PUBLIC 标识符,标识符,……

85 例: 模块1: NAME MOD1 PUBLIC VAR1 ;公用标识符VAR1
DATA1 SEGMENT PARA PUBLIC ‘DATA’ VAR1 DB ? ;字节变量VAR1 DATA1 ENDS 模块2: NAME MOD2 EXTRN VAR1:BYTE ;说明VAR1是字节 CODE2 SEGMENT PARA PUBLIC ‘CODE’ …… MOV AL,VAR1 ;访问MOD1中的字节变量VAR1

86 第六节 汇编语言程序设计 一、程序设计基本方法 分析实际问题,确定基本思路及程序算法 绘制程序流程图 根据流程图编写程序 调试程序

87 1、流程图 起止框:表示程序的开始和结束 工作框:说明该步骤的功能 判断框:说明判断的条件 调用框:说明调用过程的名字、参数等
连线: 表示程序的走向 功能 条件? 子程序 起止框 工作框 条件框 调用框 连线

88 2、程序的基本结构形式 顺序结构 分支结构 按直线顺序执行程序 含判断语句,根据判断结果选择分支 例: CMP AL,BL
JZ L1 ;相等 L2: …… ;不等 JMP NEXT L1: …… NEXT:…… 程序段1 程序段2 程序段3 顺序结构 条件? 程序段1 程序段2 分支结构 Y N

89 (3)循环结构 初始化部分 循环体部分 循环条件判断部分 例: MOV CX,100 ;初始化部分 L: …… ;循环体开始 ……
DEC CX ;修改循环变量 JNZ L ;循环条件判断 条件? 循环体 初始化 循环结构 Y N

90 (4)子程序结构 寄存器的保护与恢复 主程序与子程序之间的参数传递 子程序可嵌套调用
在程序中需要多次出现的程序段,可定义为一个子程序,在主程序需要的时候就可以直接调用它 寄存器的保护与恢复 主程序与子程序之间的参数传递 子程序可嵌套调用 程序段1 程序段2 过程调用 子程结构

91 子程序嵌套

92 二、程序设计举例 (1)顺序结构--32位无符号数相乘 H1 L1 H2 L2 L2×L1 L2×H1 H2×L1 H2×H1 64位结果
思路:分为高字部分和低字部分,模拟笔算的方法,做4次16位的乘法运 算,得到4个部分和A、B、C、D,再加起来得到结果 H1 L1 H2 L2 L2×L1 L2×H1 H2×L1 H2×H1 64位结果 被乘数 乘数 部分和A 部分和B 部分和C 部分和D × + 92

93 32位无符号数相乘流程图 开始 计算部分和C= 计算部分和A= C的低字部分叠加至RES+2 C的高字部分叠加至RES+4
计算部分和B= A的低字部分 RES A的高字部分 RES+2 B的低字部分叠加至RES+2 B的高字部分叠加至RES+4 计算部分和C= 计算部分和D= C的低字部分叠加至RES+2 C的高字部分叠加至RES+4 D的低字部分叠加至RES+4 D的高字部分叠加至RES+6 结束 开始 32位无符号数相乘流程图

94 DATA SEGMENT MUL1 DW 5678H, 1234H ;被乘数 H MUL2 DW 789AH, 3456H ;乘数 AH RES DW 4 DUP(0) ;存放64位结果,初始化为0 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MAIN PROC FAR PUSH DS MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX 94

95 ;计算部分和A=L2×L1 MOV AX, MUL2 ;AX←L2 MUL MUL1 ;(DXAX)←L2×L1 MOV RES, AX ;保存A的低字部分 MOV RES+2, DX ;保存A的高字部分 ;计算部分和B=L2×H1 MUL MUL1+2 ;(DXAX)←L2×H1 ADD RES+2, AX ;叠加B的低字部分 ADC RES+4, DX ;叠加B的高字部分 ;计算部分和C=H2×L1 MOV AX, MUL2+2 ;AX←H2 MUL MUL1 ;(DXAX)←H2×L1 ADD RES+2, AX ;叠加C的低字部分 ADC RES+4, DX ;叠加C的高字部分 95

96 相乘结果: 03B8C7B8E8544430H ;计算部分和D=H2×H1 MOV AX, MUL2+2 ;AX←H2
MUL MUL1+2 ;(DXAX)←H2×H1 ADD RES+4, AX ;叠加D的低字部分 ADC RES+6, DX ;叠加D的高字部分 RET MAIN ENDP CODE ENDS END MAIN 相乘结果: 03B8C7B8E H 96

97 (2)分支结构—符号函数的实现

98 开始 初始化指针、循环次数 读入 x的值 x AL=0FFH AL=00H AL=01H 保存AL,修改指针 完成? 结束 <0 >0 =0 N Y

99 DATA SEGMENT X DB 12H,34H,00H,0FFH,0ABH ;X的值 COUNT EQU $-X ;X的个数 SGNX DB COUNT DUP(?) ;保存结果 DATA ENDS CODE SEGMENT ASSUME CS:CODE,DS:DATA,ES:DATA MAIN PROC FAR PUSH DS MOV AX,0 PUSH AX MOV AX,DATA MOV DS,AX MOV ES,AX LEA SI,X ;初始化源指针 LEA DI,SGNX ;初始化目的指针 MOV CX,COUNT ;循环次数

100 AGAIN:LODSB ;读入X的值 OR AL,AL ;把X的特征反映在标志寄存器上 JZ ZERO ;如果ZF=0,则说明X=0 JS MINUS ;如果SF=1,则说明X<0 MOV AL,01H ;否则X>0,所以sgn(x)=1 JMP NEXT ZERO:MOV AL,00H ;X=0,所以sgn(x)=1 MINUS:MOV AL,0FFH ;X<0,所以sgn(x)=-1 NEXT:STOSB LOOP AGAIN RET MAIN ENDP CODE ENDS END MAIN

101 (3)循环结构--显示二进制数的ASCII码形式
在内存中有几个8位的二进制数,编写程序将它们转换成二进制数的ASCII码,并输出到屏幕上,例如对于字节12H,转换后能在屏幕上显示“ B”

102 开始 初始化指针SI、计数值CX DL=30H BH逻辑左移1位 N CF=0? Y 显示字符 BL减1 BL=0? SI加1,CX减1
转换完成? DL加1 N Y 结束

103 DATA SEGMENT NUM DB 12H,34H,0ABH,0CDH ;需显示的字节 COUNT EQU $-NUM ;字节数 AFTER DB 'B',0DH,0AH,'$' ;‘B’、回车换行 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA MAIN PROC FAR PUSH DS MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX 103

104 LEA SI, NUM ;数据的地址 MOV CX, COUNT ;字节数 AGAIN: MOV BH, [SI] ;需显示的数←BH MOV BL, 8 ;左移8次 PRINT: MOV DL, 30H SHL BH, 1 ;逻辑左移1位 JNC ZERO ;CF=0,则DL=30H INC DL ;CF=1,则DL=31H ZERO: MOV AH, 02H INT 21H ;显示‘0’或‘1’ DEC BL ;是否8个位都显示 JNZ PRINT ;否,则继续 LEA DX, AFTER ;显示‘B’、回车换行 MOV AH, 09H INT 21H

105 INC SI LOOP AGAIN ;循环显示所有字节 RET MAIN ENDP CODE ENDS END MAIN 运行结果: B B B B

106 (4)子程序结构--显示16进制数的ASCII码形式
在内存中有几个16位的二进制数,编写程序将它们转换成16进制数的ASCII码,并输出到屏幕上,如对于数字1234H,须将其转换成“1”、“2”、“3”、“4”四个字符,并分别送显示器显示 编程时,把对每个二进制数的处理写成一个子程序SHOW_W ,在这个子程序中,将二进制数每4位分成一段,每段又调用子程序SHOW_1 ,转换成ASCII码并输出

107 读取高8位 前4位 SHOW_1 后4位 读取低8位 显示’H’,换行 返回 (b) SHOW_W >9? DL+30H DL+7H 显示字符 (c) SHOW_1 N Y 二进制转16进制ASCII码的程序流程图 初始化SI CX←个数 SHOW_W 完成? 开始 结束 (a) MAIN

108 DATA SEGMENT NUM DW 1234H, 5678H, 9ABCH, 0DEF0H ;要显示的数字(字) LTH_W DW ($-NUM)/2 ;数字的个数(每个数占2字节) AFTER DB ‘H’, 0DH, 0AH,‘$’ ;每个数后面显示“H”然后回车换行 DATA ENDS STACK SEGMENT PARA STACK 'STACK' DB 100 DUP(?) ;堆栈长度 STACK ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, SS:STACK MAIN PROC FAR PUSH DS MOV AX, 0 PUSH AX ;保存DOS返回指令的地址 MOV AX, DATA MOV DS, AX ;初始化DS MOV CX, LTH_W LEA SI, NUM

109 L: CALL SHOW_W ;调用子程序显示一个数字
INC SI INC SI ;一个数字占用2字节 LOOP L RET MAIN ENDP SHOW_W PROC ;子程序,能将[SI]中的16位数字显示出来 PUSH CX ;保护CX MOV DL, [SI+1] ;先处理高8位 MOV CL, 4 SHR DL, CL ;前4位 CALL SHOW_1 ;显示前4位的16进制数 MOV DL, [SI+1] AND DL, 0FH ;后4位 CALL SHOW_1 ;显示后4位的16进制数

110 MOV DL, [SI] ;再处理低8位 MOV CL, 4 SHR DL, CL ;前4位 CALL SHOW_1 ;显示前4位的16进制数 MOV DL, [SI] AND DL, 0FH ;后4位 CALL SHOW_1 ;显示后4位的16进制数 LEA DX, AFTER MOV AH, 09H INT 21H ;显示数字后面的“H”,并回车、换行 POP CX ;恢复CX RET SHOW_W ENDP

111 SHOW_1 PROC CMP DL, 9 JBE NEXT ADD DL, 7 ;如果大于9,则需加37H,如‘A’=41H= H NEXT: ADD DL, 30H;如果不大于9,则需加30H,如‘1’=31H=1+30H MOV AH, 02H INT 21H ;显示一位16进制数 RET SHOW_1 ENDP CODE ENDS END MAIN 程序运行结果,屏幕上显示: 1234H 5678H 9ABCH DEF0H

112 其他例子: 逻辑尺控制程序 例:对BUF中16个字节进行处理: 将第1、3、7、12、16个数据的值减2 将其它数据的值加3 利用逻辑尺:
(AX) = B AX逻辑左移1位 移出的位 = 0:BUF[SI]的值-2; 移出的位 = 1:BUF[SI]的值+3; 循环上一步16次

113 开始 初始化指针、循环次数 读入逻辑尺的值 读入一个数据 左移逻辑尺 数据的值-2 数据的值+3 结束 N Y CF=0?
保存数据,修改指针、循环次数 循环完成? 结束 N Y

114 DATA SEGMENT BUF DB 12,23,34,45,56,67,78,89,98,87,76,65,54,43,32,21 RES DB 16 DUP(?) ;存放结果的缓冲区 LOG_RUL DW 5DEEH ;逻辑尺 DATA ENDS CODE SEGMENT ASSUME CS:CODE, DS:DATA, ES:DATA MAIN PROC FAR PUSH DS MOV AX, 0 PUSH AX MOV AX, DATA MOV DS, AX MOV ES, AX

115 LEA SI, BUF LEA DI, RES MOV BX, LOG_RUL ;读入逻辑尺常数 MOV CX, 16 ;循环次数 AGAIN: LODSB ;读入温度值 SHL BX, 1 ;逻辑尺左移 JC PROC1 ;如果CF=1则转“+3”程序段 PROC0: SUB AL, 2 ;否则CF=0,进行“-2”运算 JMP NEXT PROC1: ADD AL, 3 ;“+3”运算 NEXT: STOSB ;处理完毕保存结果 LOOP AGAIN ;循环处理 RET MAIN ENDP CODE ENDS END MAIN

116 本章结束!


Download ppt "第四章 80x86汇编语言程序设计 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第一节 汇编语言概述 第二节 汇编语言语句的组成 第三节 汇编语言的语句 第四节 宏汇编指令 第五节 编写完整的汇编语言程序 第六节 汇编语言程序设计."

Similar presentations


Ads by Google