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
开始存放
第 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
开始存放