1
第 4章
汇编语言程序设计
mov ax,12h
call display
Jmp 1234h
2
主要内容:
汇编语言源程序的结构
汇编语言语句格式
伪指令
功能调用
汇编语言程序设计
3
4.1 汇编语言源程序
机器语言 ——二进制数形式的指令和数据。
B0 64 是什么意思?这就是机器语言。既不直
观,又不易理解和记忆,
MOV AL,64H ; 很容易记忆理解,这就是 助记
符 。
助记符 ——用便于记忆的英语单词表示的指令
操作码。它反映了指令的功能和主要特征,便于人
们理解和记忆。
4
操作数可能放在存储器中,这就涉及操作数的
地址。程序中遇到转移指令或调用指令,也需要
知道转移地址,若采用具体地址就很不方便,一
旦有错,改动也很麻烦。于是人们 采用标号或
符号来代替地址,例:
LP1,mov ax,VAR

loop LP1
汇编语言 ——指令助记符,符号地址, 标号,
伪指令等语言元素的集合以及这些元素使用的
规则 。
用汇编语言编写的程序叫 汇编语言源程序 。
指令除了操作码以外,还有一个操作数问题。
5
汇编程序
源程序的编译程序
汇编程序汇编语言源程序 机器语言目标程序
汇编源程序需翻译成机器语言,变成可执
行文件,机器才能执行,这个翻译过程叫 汇
编 。 ——高级语言中称该过程为, 解释, 或
,编译, 。执行翻译的程序称为, 汇编程
序, 。
6
汇编语言程序设计与执行过程
输入汇编语言源程序 源文件,ASM
汇编(编译) 目标文件,OBJ
链接 可执行文件,EXE
调试 最终程序
7
4.1.1 汇编语言源程序的结构
汇编语言源程序通常由一个或几个程序
模块组成,每个模块一般由三个逻辑段组成:
数据段 —— 存放数据、变量
堆栈段 —— 堆栈区域
代码段 —— 存放程序指令
8
一个基本的汇编语言程序框架如下:
stack SEGMENT PARA ‘stack‘
DB 100 DUP(‘stack’)
stack ENDS
data SEGMENT
<数据、变量在此定义 >
data ENDS
code SEGMENT
ASSUME CS:code,DS:data,ES:data
start,MOV AX,data
MOV DS,AX
MOV ES,AX
<此处加入你自己的程序段 >
MOV AL,4CH
INT 21H
code ENDS
END start
堆栈段
数据段
代码段
9
4.1.2 汇编语言的语句与格式
汇编语言的语句有两种:
指令性语句 —— 由 8086指令助记符构成的语句
指示性语句 —— 由伪指令构成的语句
指令性语句 的格式为:
标号, 指令助记符 目的操作数,源操作数 ;注释
指示性语句 的格式为:
名字 伪指令 操作数 1,操作数 2,…,操作数 n ;注释
注:各部分之间至少要用一个空格作为分隔符。
10
● 指令性语句 由 CPU执行,每一条指令性语
句都有一条机器码指令与其对应;
● 指示性语句 由 汇编程序 执行。它指出汇编
程序应如何对源程序进行汇编,如何定义变
量、分配存储单元以及指示程序开始和结束
等。指示性语句无机器码指令与其相对应。
指令性语句汇编时 生成 机器码;
指示性语句汇编时 不生成 机器码。
11
语句的构成元素:
标号 ——指令的符号地址,用来代表指令在存储器中的
地址。 只能出现在指令性语句中,标号后应加上冒号。
名字 ——段、过程、变量的名字,用来代表它们在存储
器中的地址。 只能出现在指示性语句中,名字后不加冒
号。
指令助记符 ——8086助记符、伪指令
操作数 ——即指令的操作对象
– 对指令性语句 ——0,1,2个
– 对指示性语句 ——根据需要而定
– 操作数之间以逗号分隔
– 操作数可以是,寄存器、存储单元、常数或表达式
例如,AX,[DI+BX+10],200,16*8+TABLE,等等
12
注释 ——以分号开头,可放在指令后,也可
单独一行。
?注意注解的写法。要写指令(段)在程
序中的作用,而不要写指令的操作。
例如:以下为同一条指令写的注释
1) MOV CX,100 ;传送 100到 CX
2) MOV CX,100 ;循环计数器置初值
显然,第二种写法要比第一种写法要好。
13
汇编语言的一个实例, hello.asm
data SEGMENT
Hello DB ‘Hello,world!’,0DH,0AH,’$’
data ENDS
prog SEGMENT
ASSUME CS:prog,DS:data
start,MOV AX,data
MOV DS,AX
LEA DX,hello ;取字符串首地址
MOV AH,9
INT 21H ;显示字符串
MOV AH,4CH
INT 21H ;退回 DOS
prog ENDS
END start
名字
标号
14
4.1.3 数据项与表达式
数据项包括 常量, 变量, 标号 及 表达式 。
1.常量
?二进制数,以 B结尾。如 01001101B。
?十进制数,如 85。
?十六进制数,以 H结尾 。 第 1个数字为 A-F时, 前
面应加 0,如 0F160H。
?字符串:用引号括起来的 1个或多个字符 。 如
‘ ERROR!’,’a’,汇编时被翻译成对应的 ASCII
码 45H,52H,52H,4FH,52H,21H和 61H。
15
?有三个属性:
段地址,即标号所在段的段地址;
偏移量,标号所代表存储单元的段内偏移地址;
类 型, NEAR或 FAR:
NEAR—表示标号所在语句与转移指令 /
调用指令在同一码段内,跳转时
只需改变 IP即可。
FAR—标号所在语句与转移指令 /调用
指令不在同一代码段内。
?若没有对类型进行说明,默认为 NEAR。
?标号通常作为 转移指令 或 CALL指令 的转移地址。
2.标号 ——指令所在内存单元的符号地址
16
变量 ——即内存中的存储单元或数据区。
变量名 ——是存储单元 (数据区 )的符号地
址或名字。
?变量也有三个属性,
?段地址 —变量所在段的段地址
?偏移量 —变量单元地址与段首地址之间的位移量。
?类 型 —有 BYTE,WORD和 DWORD三种 。
?变量在程序中作为 存储器操作数 被引用。
3.变量
17
标号和变量名的使用规则
– 组成,A-Z(不分大小写 ),0-9,? @, _ $
– 不能以数字开头,句号 (.)只能作为首字符
– 长度小于 31个字符
– 不能与保留字 (指令助记符、伪指令、预定义符
号等 )重名
– 不能重复定义
例如:
正确的,LP1,AGAIN,NEXT,_GO,OK_1
错误的,4M,LOOP,AAA,#HELP,+ONE
18
4.表达式
?表达式是常数、寄存器、标号、变量与
运算符的组合。
?有数字表达式和地址表达式两种。
?汇编时按优先规则对表达式进行计算,
计算出具体的数值或地址。运行时不能改
变。
?表达式中的运算符有 6类:算术、逻辑、
关系、取地址、属性、杂类。
19
?用于数字表达式,例:
MOV AX,4*1024
汇编后的形式为,
MOV AX,4096
?用于地址表达式,例,
LEA SI,TAB+3
若 TAB的偏移地址为 1000H,则汇编后的形式
为:
LEA SI,[1003H]
1)算术运算符 —— +,-,*,/,MOD
20
逻辑运算符只能用于数字表达式中。
例,MOV CL,36H AND 0FH
经汇编后,MOV CL,06H
注意,不要把逻辑运算符与逻辑运算指令混淆:
例,AND AX,3FC0H AND 0FF00H
汇编后源操作数被翻译为,3F00H,所以上述指
令与 AND AX,3F00H等价。
2)逻辑运算符 —— AND,OR,XOR,NOT
21
?关系运算的结果是一个逻辑值,真 或 假
关系为真,结果为全 1
关系为假,结果为全 0
例,MOV BX,PORT GT 300H
若 PORT的值大于 300H,则汇编后为:
MOV BX,0FFFFH
否则汇编后为:
MOV BX,0
3)关系运算符 ——EQ,NE,LT,GT,LE,GE
22
SEG:取变量 /标号的段地址
OFFSET:取变量 /标号的偏移地址
例,VAR DB 12H
……
MOV BX,OFFSET VAR ;取变量 VAR的偏移地址
MOV AX,SEG VAR ;取变量 VAR的段地址
注意,以下指令的异同:
MOV BX,OFFSET VAR
LEA BX,VAR
?OFFSET只能取静态的偏移地址;
?LEA指令即可取静态的偏移地址,也可取动态的偏移地址。
4)取地址运算符 ——SEG,OFFSET
23
TYPE 取 变量的类型( 1,2,4)
LENGTH 取所定义 变量 的长度
(即 变量 中元素的个数)
SIZE 取所定义存储区的字节数
( =TYPE*LENGTH)
例,VAR DW 1,2,3,4,5
则 TYPE VAR = 2
LENGTH VAR = 5
SIZE VAR = 10
5)取值运算符 ——TYPE,LENGTH,SIZE
24
6)属性运算符 ——PTR
?用来指定地址操作数的类型。
格式,<类型 > PTR <地址操作数 >
类型 ∈ {BYTE,WORD,DWORD,NEAR,FAR}
BYTE,WORD,DWORD
用于描述数据存储单元 (变量 )地址
NEAR,FAR
用于描述转移、调用的目的地址
25
例,MOV BYTE PTR[DI],0 ;字节类型
MOV WORD PTR[DI],0 ;字类型
MOV [DI],0B5H ;类型不定
?PTR也可用来进行强制类型转换
例,STR1 DW? ;STR1定义为字类型
MOV AX,STR1 ;合法
MOV AL,STR1 ;非法
MOV AL,BYTE PTR STR1 ;合法
26
4.2 伪指令
数据定义伪指令
符号定义伪指令
段定义和段寄存器指定伪指令
过程定义伪指令
结束伪指令
由汇编程序执行的指令,它本身不被汇编
成机器指令。常用的伪指令有:
27
4.2.1 数据定义伪指令
用于定义变量,即内存单元或数据区。数
据定义伪指令的格式为:
变量名 数据定义伪指令 操作数,操作数,…
?常用的数据定义伪指令有如下几种:
DB 定义 字节
DW 定义 字
DD 定义 双字
?操作数可以是常数、变量或表达式
28
例 1:
DATA_B DB 10,5,10H
DATA_W DW 100H,-4
DATA_D DD 0FFFBH
汇编后的内存分配情况
如右图所示。
05H
10H
00H
01H
FCH
FFH
FBH
FFH
00H
00H
0AHDATA_B
DATA_W
DATA_D
10
5
10H
100H
-4
0FFFBH
29
例 2:操作数可以是字符串,例如
STR DB ‘HELLO’
汇编后的情况如图:
STR ‘
H’‘
E’‘ L’
‘ L’

O’
注意下面两个定义的不同之处:
DB ‘AB’ ;41H在低字节,42H在高字节
DW ‘AB’ ;42H在低字节,41H在高字节
48H
45H
4CH
4CH
4FH
30
操作数?用来保留存储空间,但不存入数据,
例 3,ABC DB 0,1,2,3,4,’OK’,’$’
RSV DW?,?,?,?,?,?,?,?
?复制操作符 DUP:
重复的数据可以使用复制操作符 DUP,如上
面 RSV亦可写成,
RSV DW 8 DUP(?)
若操作数中若使用 $,则表示的是地址计数
器的当前值。
31
例,TABLE DB 10 DUP(?)
BUFFER DW TABLE,$+3
设 TABLE的偏移地址为 0080H,则汇编后如
下图所示:
BUFFER
0080H
80H
TABLE
008AH
008BH
008CH
008DH
...
8FH
00H
00H
0089H
10 Bytes
32
4.2.2 符号定义伪指令
把一个表达式用一个符号表示,以后凡出
现该表达式的地方都可用这个符号表示。类
似于 C语言中的 #define。
符号定义伪指令有两种,EQU,=
? 用 EQU定义的符号未清除前,不能重新定
义。清除 EQU定义可用 PURGE伪指令。
? 用,=”定义的符号可在任何时候进行重定
义。
? 二者 均不占用存储空间,仅是给符号赋值
33
例,FIVE EQU 5
COUNT EQU CX
TEN EQU 10
DIST = BYTE PTR[SI+BP]
GOTO = JMP

MOV AX,TEN
MOV CX,COUNT
ADD DIST,FIVE
DIST = WORD PTR[SI+BP+1]
ADD DIST,AX
GOTO LABEL
定义
引用
34
4.2.3 段定义伪指令
?汇编语言程序是按段来组织程序和数据的。
和存储器的物理段相对应,汇编语言程序中
的段称为逻辑段。汇编连接后被映射到物理
段中。
?三类段:代码 (程序 )、数据、堆栈
?段定义伪指令,SEGMENT,ENDS,ASSUME,ORG
?定义一个段的基本格式:
段名 SEGMENT [定位类型 ][组合方式 ][类别 ]
<汇编语言语句 >
段名 ENDS
35
? 这两个伪指令总是成对出现,二者前面的
段名应一致。 SEGMENT说明了一个段的开
始,ENDS说明了一个段的结束。
? 对数据段和堆栈段,段中的语句一般是变
量定义。对代码段则是指令语句。
如,data SEGMENT
<指令语句 >
data ENDS
SEGMENT和 ENDS伪指令
36
ASSUME伪指令
?在代码段中,还必须明确段和段寄存器的
关系,这由 ASSUME语句来指定。如
ASSUME CS:code,DS:data,ES:data
语句中的 code和 data为段名。
这个语句说明:
1,CS将指向名字为 code的代码段
2,DS和 ES将指向名字为 data的数据段
37
但要注意,ASSUME伪指令只是告知汇编程序
有关段寄存器与段的关系,并没有给段寄存
器赋予实际的初值。故下面的语句
MOV AX,DATA
MOV DS,AX
MOV ES,AX
将段基址装入段寄存器 。如果程序中用到
堆栈段,则 SS也需装入实际的初值。
代码段基地址 不需要程序员装入 CS寄存器,
而由 OS负责装入。
38
SEGMENT语句后可以带有可选参数, 用以 规定
逻辑段的其他一些 属性 。
1) 定位类型
说明 如何确定逻辑段的边界。有四种:
? PARA(Paragraph),逻辑段从一个节 (16个字节 ) 的边
界开始。 即 段的起始地址应能被 16整除,或这说段 起始
物理地址应为 ×××× 0H。 ——默认类型
? BYTE, 逻辑段从字节边界开始,即段可以从任何地
址开始。
? WORD, 逻辑段从字边界开始。即段的起始地址必须
是偶数。
? PAGE, 逻辑段从页边界开始。 256字节称为一页,故
段的起始物理地址应为××× 00H。
39
2) 组合类型
说明不同模块中同名段的组合方式。
?PUBLIC,所有此类型的 同名段 组合成一个逻辑段,
公用一个段地址,运行时装入同一个物理段中。
?COMMON, 所有此类型的同名段具有相同的起始
地址 (覆盖 ),共享相同的存储区域。
?AT <数值表达式 >, 按绝对地址定位,段地址就是
表达式的值。
?STACK, 专用于说明堆栈段,组合方式同 PUBLIC
40
3) 类别
用单引号括起来的字符串。所有同类别的段被安
排在连续的存储区域中。
如:在模块 1中有段定义:
seg1 SEGMENT PARA STACK ‘stack’

seg1 ENDS
在模块 2中有段定义:
seg2 SEGMENT PARA STACK ‘stack’

seg2 ENDS
则连接时这两个段被安排在一起。
41
ORG规定了段内的指令或数据存放的开始地址
(偏移地址的初值 ),其格式为:
ORG <表达式 >
表达式的值即为开始地址, 从此地址起连续存放
程序或数据 。
例,ABC SEGMENT
ORG 100H
begin,…

ABC ENDS
ORG伪指令
指令从 100H
开始存放
42
作业:
P193
4.1,4.2,4.12,4.15