1
第三章 汇编语言程序设计第一节 汇编语言上机过程第二节 汇编语言程序结构第三节 指示性语句第四节 汇编语言程序举例第五节 BIOS和 DOS功能调用第六节 汇编语言程序设计
2
作业,3-2,3-6,3-7,3-9,3-12
复习内容,P97--P114
预习内容,P114-P140
P145-147(不作要求,自学)
3
上机环境硬件系统软件应用软件操作系统,DOS系统编辑器,EDIT.exe
编程序,MASM.exe
连接程序,LINK.exe
调试程序,DEBUG.exe
用户开发的程序,ABC.exe等
CPU、存储器 (ROM,RAM),I/O接口、输入、输出设备
4
第一节 汇编语言上机过程
D:>EDIT ABC.asm
D:>MASM ABC;
有语法错,回 EDIT下改该程序
D:>LINK ABC;
有错,回在 EDIT下改程序
D:>ABC
运行结果错,回 EDIT下改程序或在 DEBUG下调试,找原因 。
D:>DEBUG ABC.exe
编辑源程序 EDIT ABC.ASM
汇编源程序 MASM ABC.ASM
形成目标程序 ABC.OBJ
连接目标程序 LINK ABC.OBJ
有连接错误信息?
形成可执行程序 ABC.EXE
装入可执行程序到内存,并执行
D:\>sub>ABC
下一程序用 DEBUG 调试可执行程序
D:\>sub>DEBUG ABC.EXE 找到原因
Y
N
Y
N
N
Y
N
有汇编错误信息?
Y运行结果正确?
用 DEBUG调试程序查错?
5
第二节 汇编语言程序结构一,程序结构二,语句结构
6
汇编语言程序结构例一程序,movs.asm
功能,实现数据传送功能数据段 1 传送到 数据段 2
目的,学习程序结构
7
一,程序结构
程序由数条语句构成,每条语句占一行 。
指令性语句 (指令语句 )
指示性语句 (伪指令语句 )
分段结构程序按段编写,与 8088内存分段编址相对应 。
每段由伪操作 SEGMENT开始,由 ENDS结束 。
程序最后为 END结束语句,后跟一启动地址 。
启动地址指示程序开始执行的第一条语句 。
程序中设有返回 DOS的功能 。
使程序执行完后返回 DOS系统的命令接受状态 。
程序中用到内存操作数时,
应按操作数的寻址方式,给相应的段寄存器赋值;汇编语言程序结构例一 movs.asm;实现数据传送功能
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,SEG str2
MOV ES,AX
MOV DI,OFFSET str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H ;返回 DOS
cc ENDS
END start ;指示程序结束
8
汇编语言程序结构例二程序,scans.asm (子程结构)
子程内容,用二进制显示 BX内容功能,实现用二进制显示中断向量表中 ( 0,0~0,3FFH)
数据 D0H的个数目的,了解程序可由多个段构成
9
程序可由多个段构成,至少有一个代码段;汇编语言程序结构例二 ( 子程结构 ) scans.asm;用二进制显示中断向量表中 ( 0,0~0,3FFH) 数据 D0H的个数
key EQU 0D0H ;用符号表示常量 (关键字 )
code SEGMENT ;代码段开始
ASSUME CS:code
begin,MOV AX,0000H
MOV DS,AX
MOV SI,0000H
MOV CX,0400H
MOV BX,0
MOV AL,key
next,CMP [ SI ],AL
JNZ point
INC BX
point,INC SI
LOOP next
CALL display ; 调用显示子程
MOV AH,4CH ; 返回 DOS
INT 21H;用二进制显示 BX内容子程
display PROC
MOV CX,16
rotate,ROL BX,1
MOV DL,BL
AND DL,01H
ADD DL,30H
MOV AH,2H
INT 21H
LOOP rotate
RET ;子程返回
display ENDP
code ENDS ;代码段结束
END begin ;指示程序结束和;程序入口
10
二、语句结构
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
data SEGMENT ;数据段
var DB?
data ENDS
code SEGMENT ;代码段
ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV var,CL
MOV AH,4CH
INT 21H ;返回 DOS
code ENDS
END start
例:
11
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
1,名字项
据语句功能的不同,
名字项可用来表示,
段名,变量名,
标号,过程名以及常量名 等 。
data SEGMENT ; 数据段
var DB?
data ENDS
code SEGMENT ;代码段
ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV var,CL
MOV AH,4CH
INT 21H ;返回 DOS
code ENDS
END start
12
名字项用一个符号表示。
对符号的规定,
① 由字符 A~Z,a~z,0~9及符号 @,$、下划线 _ 等组成,
最长 31个字符,超出部分忽略。
② 不能用数字打头,以免与十六进制数相混。
③ 不使用汇编程序中的保留字。 (如指令的助记符等 )
④ 对定义的符号不区分大小写。
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
13
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
2,助记符项助记符可以是指令,伪操作中的助记符 。
对于指令,汇编程序将其翻译成机器语言指令。
MOV AX,100 → B8 00 01
对于伪操作,汇编程序据其要求的功能进行处理。
data SEGMENT → data与一段值对应
string DB ‘Tsinghua’ → string与一内存地址对应
14
3,操作数项
操作数给出参与操作的数或数所在的地方 。
操作数多于一个时,用逗号分开 。
操作数可以是 常数,寄存器,存储器操作数,
标号名,过程名或 表达式 等 。
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
15
常数给出具体的数据 。 可以是数字常量或字符常量 。
◢ ◢ 数字默认十进制,也可加 D表示十进制数 。 如 1234D,1234
◢ ◢ 数字后加 B表示二进制数 。 如 1010B
◢ ◢ 数字后加 H表示十六进制数 。 如 1234H
◢ ◢ 字符常量,用单引号表示 。 如 ‘ 1234’
汇编时,用字符对应的 ASCII表示 。 如 31H,32H,33H,34H
例 data1 DB 12,34,56 ;十进制
data2 DB 12H,34H,56H ;十六进制
MOV AL,‘G’ ;字符
string DB ‘1234’ ;字符串
16
A,B,C,D,E,F开头的十六进制数前面加 0,
与 H结尾的标识符区别 。
如 寄存器名 AH,BH,CH,DH
变量名 abcdH 等例 mov AL,0AH
mov AL,AH
mov BX,0abcdH
17
4,注释项
由分号引出,用来说明语句或程序的功能 。
汇编程序对分号后的内容不做处理 。
作用,① 注释程序,增强程序可读性 。
② 可放在语句最前,暂时注释某语句,调试程序用 。
例,、、; MOV AH,2 ;显示提示信息; MOV DL,’A’; INT 21H
、、、
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
18
第三节 指示性语句 / 第四节 汇编语言程序举例一,程序开始和结束二,段定义三,变量定义四,ASSUME语句
汇编语言程序 举例一了解 DOS的返回,装入功能五,表达式及表达式中的操作符
汇编语言程序例二六,过程定义 (第五节程序设计介绍 )
七,等值定义 (第五节程序设计介绍 )
汇编语言程序例三 (第五节程序设计介绍 )
19
指示性语句与指令性语句:
指令性语句 是用指令系统中的指令构成的语句 。
例 MOV AX,BX
指示性语句 是指示汇编程序进行汇编的操作 。
例 MOV AX,4 + 8 中的 +
code SEGMENT 中的 SEGMENT
MOV BX,OFFSET string 中的 OFFSET
20
指示性语句与指令性语句区别一个程序经汇编,连接和装入内存后,在执行程序之前:
◢ 指示性语句的功能已经完成,故又称伪操作 。
◢ 而指令性语句的功能尚未完成,需控制 CPU去执行,才能完成 。
21
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,bb
MOV ES,AX
LEA DI,str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello2.exe
-U,查看代码段
12A0:0000 FC CLD
12A0:0001 B89E12 MOV AX,129E
12A0:0004 8ED8 MOV DS,AX
12A0:0006 8D360000 LEA SI,[0000]
12A0:000AB89F12 MOV AX,129F
12A0:000D 8EC0 MOV ES,AX
12A0:000F 8D3E0000 LEA DI,[0000]
12A0:0013 B90600 MOV CX,0006
12A0:0016 F3 REPZ
12A0:0017A4 MOVSB
12A0:0018 B44C MOV AH,4C
12A0:001ACD21 INT 21
、、、
-D 129E:0 L10 ;查看数据段 1的内容
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00
Hello!..........
-D 129F:0 L10 ;查看数据段 2的内容
129F:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
数据传送源程序 hello2.asm 程序经汇编、连接后,装入内存的情况如下:
22
常用伪操作介绍一,程序开始和结束二,段定义三,变量定义四,ASSUME语句五,表达式中的操作符六,过程定义七,等值定义
23
一,模块定义和程序结束伪操作
1,NAME 和 TITLE 伪操作格式 NAME 模块名格式 TITLE 模块名
▲ 在源程序开始可用 NAME 或 TITLE 为模块命名,
模块名的作用是指示给连接程序进行连接用 。
▲ 源程序中可无模块定义,此时源文件名作为模块名 。
24
2,END伪操作格式 END 启动地址
▲ 作用是指示源程序到此结束 。
汇编程序对 END 之后的语句不进行处理 。
程序中所有有效语句应放在 END 语句之前 。
▲ 源程序中必须有 END 结束语句 。
汇编程序对无 END 语句的源程序不进行处理,
只给出无 END 语句错误信息 。
25
假设 TEST.asm 是一个无 END 语句的汇编语言源程序 。
其汇编结果如下,
D:\ MASM TEST;↙
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
End of file encountered on input file
End of file encountered on input file
49968 + 421181 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\
由于没有 END语句,汇编程序根本没对源程序进行汇编,
此时显示警告性错误总数为 0,严重性错误总数为 0,
用户不要被此值的误导 。
26
▲ 启动地址可是一个标号或过程名,指示程序的入口 。
程序装入内存后,系统跳转到入口处,开始执行程序 。
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,SEG str2
MOV ES,AX
MOV DI,OFFSET str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello.exe
-U,查看代码段
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[0000]
129F:000AB89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000FBF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、
-D 129d:0 l10 ;查看数据段 1的内容
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00
00 Hello!..........
-D 129e:0 l10 ;查看数据段 2的内容
129E:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
27
二,段定义伪操作格式 段名 SEGMENT
、、、
、、、
段名 ENDS
▲ 段定义由伪操作 SEGMENT开始,ENDS结束 。
其中,SEGMENT 和 ENDS 必须成对出现,
且语句前必须有段名,段名必须相同 。
▲ SEGMENT和 ENDS语句之间可以有指令和其他伪操作,
表示存放在该段内存的变量,指令或其他伪操作对该段内存的处理
▲ 程序中可以定义多个段 。
▲ 程序经汇编,连接及装入内存后,段名为一具体的段值 。
28
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,bb
MOV ES,AX
LEA DI,str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello2.exe
-U,查看代码段
12A0:0000 FC CLD
12A0:0001 B89E12 MOV AX,129E
12A0:0004 8ED8 MOV DS,AX
12A0:0006 8D360000 LEA SI,[0000]
12A0:000AB89F12 MOV AX,129F
12A0:000D 8EC0 MOV ES,AX
12A0:000F 8D3E0000 LEA DI,[0000]
12A0:0013 B90600 MOV CX,0006
12A0:0016 F3 REPZ
12A0:0017A4 MOVSB
12A0:0018 B44C MOV AH,4C
12A0:001ACD21 INT 21
、、、
-D 129E:0 L10 ;查看数据段 1的内容
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00
Hello!..........
-D 129F:0 L10 ;查看数据段 2的内容
129F:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
数据传送源程序,程序经汇编、连接后,装入内存的情况如下:
29
三,变量定义伪操作格式 变量名 类型助记符 操作数 [,操作数,..,]
▲ 用来定义程序中所用的内存操作数 。
其中 变量名 指示内存操作数的地址 ( 符号地址 )
类型助记符 指示内存操作数的类型 (字节,字,双字等 )
操作数 指示内存操作数的内容
▲ 汇编程序将定义的操作数,按其类型分配内存单元数,
顺序存入变量名指向的内存单元中 。
▲ 常用的类型助记符有:
DB 指示其后的操作数为字节类型
DW 指示其后的操作数为字类型
DD 指示其后的操作数为双字类型
30
例 1,定义赋初值的变量
data SEGMENT
xx DB 1,-1,0fcH
yy DW 1,-1,0fcH
zz DD 1,- 1,0fcH
data ENDS
xx
yy
zz
01
FF
FC
01
00
FF
FF
FC
00
01
00
00
00
FF
FF
FF
FF
FC
00
00
00
1
- 1
FC
1
- 1
FC
1
- 1
FC
31
例 2,定义字符串变量 ( 只能用 DB定义 )
data SEGMENT
str1 DB ' TsingHua '
str2 DB 'INPUT:',0dH,0aH,'$'
data ENDS
注意,3个及其以上的字符,
只能用 DB定义
str1 DW ‘abcd’
str2 DD ‘abcd’
str1
str2
54
73
69
6e
67
48
75
61
49
4e
50
55
54
3a
0d
0a
24
‘T’
‘s’
‘i’
‘n’
‘g’
‘H’‘u’
‘a’
‘I’
‘N’
‘P’
‘U’
‘T’
‘:’0dH
0aH
‘$’
32
▲ 操作数可以是用 常量,表达式和? 表示 。
常量和表达式 表示内存操作数的初始值,
其值应在其定义的类型范围内,否则汇编出错 。
例 aa DB 270
bb DW 80000
用? 表示不置初始值的内存操作数 。
例 cc DB?
可用 DUP 复制操作符 定义相同的操作数,其格式为重复次数 DUP( 操作数 )
例 ee DB 3 DUP ( 4 )
等价于 ee DB 4,4,4
33
data SEGMENT
xx DB 1,-1,0FCH
yy DW 1,- 1,0FCH
zz DD 1,-1,0FCH
str DB 'TsingHua'
buf DB 4,?,4 DUP (?)
DB ‘dataend’
data ENDS
code SEGMENT
ASSUME CS:code
ASSUME DS:data
start,MOV AX,data
MOV DS,AX
LEA BX,xx
LEA SI,yy
LEA DI,zz
MOV AH,4CH
INT 21H
code ENDS
END start
D:\ MA SM > D E B UG v ari ble,e xe
- U
12A 1:0 000 B 8 9E 12 MO V AX,129E
12A 1:0 003 8 E D8 MO V DS,AX
12A 1:0 005 8 D 1E 000 0 LEA BX,[0000]
12A 1:0 009 8 D 360 300 LEA SI,[0003 ]
12A 1:0 00 D 8 D 3E 090 0 LEA DI,[0009]
12A 1:0 01 1 8 D 1E 150 0 LEA BX,[0015]
12A 1:0 015 8 D 361 D0 0 LEA SI,[001D]
12A 1:0 019 B 4 4C MO V AH,4C
12A 1:0 01B C D2 1 INT 21
12A 1:0 01 D F F 362 43E PUSH [3E2 4]
-D 1 29E,0 L 30
129E,0 000 01 F F FC 0 1 0 0 F F F F F C-00 0 1 00 00 0 0 F F F F F F,.,..,..,..,,..,
129E,0 010 FF FC 00 0 0 0 0 5 4 73 69 -6E 6 7 4 8 7 5 6 1 0 4 0 0 00,.,.,T singH ua,..
129E,0 020 00 0 0 0 0 6 4 6 1 74 61 65 -6E 6 4 00 0 0 0 0 00 0 0 00,.,d atae nd...,..
129E,0 030 B8 9E 12 8E D8 8D 1 E 0 0-00 8D 3 6 0 3 00 8 D 3E 09,..,..,..,6..,>.
-
xx
yy
zz
str buf
‘d a t a e n d’
段名 d a t a
变量 xx
变量 yy
变量 zz
变量 s tr
变量 b u f
例 4,在 DEBUG下查看变量存放情况。
34
四,ASSUME伪操作格式 ASSUME 段寄存器:段名 [,段寄存器,段名,… ]
其中 段寄存器 为 CS,DS,ES,SS中的一个段名 为用伪操作 SEGMENT定义过的段名例 ASSUME CS,cc,DS:aa
▲ ASSUME 伪操作的作用指示汇编程序指令中用到的标号,过程及变量所在的段 。
其中 对标号,过程必须用 CS 段寄存器指示对变量可用 CS,DS,ES,SS段寄存器指示
35
▲ 若未用 ASSUME语句指示指令中用到的标号,
过程和变量所在的段,汇编程序将给出错误信息 。
▲ ASSUME语句只起指示作用,并无实际的操作 。
在程序中引用定义的变量做内存操作数时,
需按寻址方式用传送指令 ( 如 MOV) 给相应的段寄存器赋值 。
36
例 用程序实现 1234H + 5678H
va lu e
r esu lt
34
12
78
56
00
00
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值
MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
37
注释掉 ASSUME语句,其汇编结果:
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT; ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV AX,value
ADD AX,value+2
MOV result,AX
MOV AH,4CH
INT 21H
code ENDS
END start
D:\MASM>MASM assume;
Microsoft (R) MacroAssembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights
reserved.
assume.ASM(8),Missing or unreachable CS
assume.ASM(10),Cannot address with segment register
assume.ASM(11),Cannot address with segment register
assume.ASM(12),Cannot address with segment register
49872 + 421341 Bytes symbol space free
0 Warning Errors
4 Severe Errors
D:\MASM>
38
程序中有 ASSUME语句,经汇编,连接和装入内存后的情况:
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值
MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
D:\MASM>DEBUG assume.exe
-R ;查看程序执行前各寄存器
AX=0000 BX=0000 CX=0023 DX=0000
SP=0000 BP=0000 SI=0000 DI=0000
DS=1295 ES=1295 SS=12A5
CS=12A6 IP=0000
NV UPEI PL NZ NA PO NC
12A6:0000 B8A512 MOV AX,12A5
-U ;查看在内存的程序
12A6:0000 B8A512 MOV AX,12A5
12A6:0003 8ED8 MOV DS,AX
12A6:0005A10000 MOV AX,[ 0000 ]
12A6:0008 03060200 ADD AX,[ 0002 ]
12A6:000CA30400 MOV [ 0004 ],AX
12A6:000F B44C MOV AH,4C
12A6:0011 CD21 INT 21
、、、、、
-注意:
程序装入内存后,执行程序前,
当前的 DS值并非程序定义的 data段值,1295 不等于 12A5
39
思考,如果上例中没有 MOV DS,AX 程序执行的结果会怎样?
D:\MASM>DEBUG assume.exe
-R ;查看程序执行前各寄存器
AX=0000 BX=0000 CX=0023 DX=0000
SP=0000 BP=0000 SI=0000 DI=0000
DS=1295 ES=1295 SS=12A5 CS=12A6 IP=0000
NV UPEI PL NZ NA PO NC
12A6:0000 B8A512 MOV AX,12A5
-U ;查看在内存的程序
12A6:0000 B8A512 MOV AX,12A5
12A6:0003A10000 MOV AX,[ 0000 ]
12A6:0006 03060200 ADD AX,[ 0002 ]
12A6:000AA30400 MOV [ 0004 ],AX
12A6:000D B44C MOV AH,4C
12A6:000F CD21 INT 21
、、、、、
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值; MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
40
结论:
1,ASSUME语句只起指示作用,没有赋值作用
2,程序中用到内存操作数时,
应按操作数的寻址方式,给相应的段寄存器赋值 。
41
第三节 指示性语句 / 第四节 汇编语言程序举例一,程序开始和结束二,段定义三,变量定义四,ASSUME语句
汇编语言程序 举例一了解 DOS的返回,装入功能五,表达式及表达式中的操作符
汇编语言程序例二六,过程定义 (第五节程序设计介绍 )
七,等值定义 (第五节程序设计介绍 )
汇编语言程序例三 (第五节程序设计介绍 )
42
汇编语言程序 举例一
43
例 将 BL寄存器的内容按二进制形式显示出来
1 0 1 0 0 1 1 0(BL)
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
、、、
31 30 31 30 30 31 31 30
44
code SEGMENT
ASSUME CS,code
start:
...
...
...
...
code ENDS
END start
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
45
D:\>MASM SBL;? 汇编成 ShowBL.obj
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
48912 + 447243 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK SBL;? 连接成 ShowBL.exe
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>SBL? 装载并执行 ShowBL.exe
请猜想执行的结果?
46
D:\>DEBUG SBL.exe? ;用 DEBUG装入程序
-U?
0B5E:0000 B90800 MOV CX,0008
0B5E:0003 D0E3 SHL BL,1
0B5E:0005 7205 JB 000C
0B5E:0007 B230 MOV DL,30
0B5E:0009 EB03 JMP 000E
0B5E:000B 90 NOP
0B5E:000C B231 MOV DL,31
0B5E:000E B402 MOV AH,02
0B5E:0010 CD21 INT 21
0B5E:0012 49 DEC CX
0B5E:0013 75EE JNZ 0003
0B5E:0015 09E8 OR AX,BP
0B5E:0017 96 XCHG SI,AX
0B5E:0018 00F8 ADD AL,BH
0B5E:001A B262 MOV DL,62
0B5E:001C FFFF DI
0B5E:001D EB0A JMP 0029
-
hello.exe
用户程序与用户程序相连的内存内容被看作程序时死机
47
▲ 复习 DOS系统的启动过程执行用户程序后,
若要返回 DOS状态,
即在屏幕上出现 DOS提示符,
等待输入新的命令,
应在用户程序的最后安排完成此功能的程序段 。
FF FF,0000 H
1
2
4
3
ROM
系统检测程序
IO,SY S 模块
COM MAN D,CO M
MS DOS,SY S 模块用户程序空 间引导程序
1K B 中断向量表
RA M
内 存
ROM BIO S
DO S
IO,SY S
COM MAN D,CO M
MS DOS,SY S
引导程序磁 盘
EDIT,EX E
MA SM,EX E
LINK,E XE
DE BUG.e x e
应用程序其他系统程序
he llo,asm
he llo,obj
he llo,exe
通常采用调用
DOS 系统功能完成 。
48
调用 DOS系统的 4CH 功能,返回 DOS
方法,在要返回 DOS 处,安排指令:
MOV AH,4CH
INT 21H
执行完 4CH的功能调用,即返回 DOS 。
例 code SEGMENT
ASSUME CS,code
start:,、,;程序主体部分
、、、
、、、
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
49
code SEGMENT
ASSUME CS,code
start:
...
...
...
...
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
MOV BL,53H ;设置一个测试 53h
50
D:\>MASM ShowBL; 汇编成 ShowBL.obj
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
48912 + 447243 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK ShowBL; 连接成 ShowBL.exe
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>ShowBL 装载并执行 ShowBL.exe
01010011
D:\masm>
51
D:\>DEBUG ShowBL.exe? ;用 DEBUG装入程序
-U?
0B5E:0000 B90800 MOV CX,0008
0B5E:0003 D0E3 SHL BL,1
0B5E:0005 7205 JB 000C
0B5E:0007 B230 MOV DL,30
0B5E:0009 EB03 JMP 000E
0B5E:000B 90 NOP
0B5E:000C B231 MOV DL,31
0B5E:000E B402 MOV AH,02
0B5E:0010 CD21 INT 21
0B5E:0012 49 DEC CX
0B5E:0013 75EE JNZ 0003
0B5F:0015 B44C MOV AH,4C
0B5F:0017 CD21 INT 21
-
52
code SEGMENT
ASSUME CS,code
start:
… ;程序主体部分
...
...
...
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
一个完整汇编程序的基本框架,
53
DOS的装入功能 (又称 EXEC系统功能 )
可执行文件,exe,应装入内存方能执行 。
由 DOS的装入功能完成 。
在 DOS的提示符后输入可执行文件的文件名,
按回车键,DOS系统即调用装入功能,
将可执行程序装入内存 。
54
内 存
256K B RO M
000 0,0000H
004 0,0000H
A000:0000H
C800:0000H
FE00:0000H
FE00:1FFF H
640K B R AM
基本内存显示器显示缓存区
ROM BIO S
系统检测程序
IO,SY S 模块
CO MMAND,CO M 常驻 模块
MS DOS,SY S 模块用户程序空间
CO MMAND,CO M 暂驻 模块
DO S 工作区
BIO S 工作区
1K B 中断向量表
128K B R AM
保留区
DO S
其他系统程序磁 盘应用程序
IO,SY S
COM MAN D,CO M
MS DOS,SY S
引导程序
EDIT,EX E
MA SM,EX E
LINK,E XE
DE BUG.e x e
hel lo.asm
hel lo.o bj
hel lo.e xe
sc ans.asm
sc ans.obj
sc ans.e xe
55
完成以下操作:
确定内存可用部分,
以便存放要执行的,exe 文件。
建立程序段前缀 PSP
( Program Segment Prefix)
◢ 程序段前缀大小 100H,
即 256个字节。
◢ 存放进程间的控制信息。
◢ PSP最开始的两个字节 CD 20,
是一条 INT 20H指令。
装入可执行程序,exe
000 0,0 000H
可用内存空间内 存
FF FF,0 00 0 H
ROM BIO S
系统检测程序
COM M AN D,COM
DO S 系统
1K B 中断向量表
CD 20
,、、
,、、
,、、
hel lo,exe
xxx x,0 000H
xxx x,0 0FFH
程序段前缀用户程序
DOS的装入功能
56
修改以下寄存器的值
◢ DS,ES设置为程序段前缀所在内存的段值;
(DS)=xxxxH
(ES)=xxxxH
◢ SS,SP设置为由连接程序传过来的值;
◢ CS,IP设置为程序的入口地址,
即伪操作 END后跟的符号名对应的物理地址;
此时 CS:IP 指向用户程序,
开始执行用户程序 。
000 0,0 000H
可用内存空间内 存
FF FF,0 00 0 H
ROM BIO S
系统检测程序
COM M AN D,COM
DO S 系统
1K B 中断向量表
CD 20
,、、
,、、
,、、
hel lo,exe
xxx x,0 000H
xxx x,0 0FFH
程序段前缀
CS,I P
57
D:\>DEBUG ShowBL.exe
-R? ;查看当前寄存器内容
AX=0000 BX=0000 CX=001B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B51 ES=0B51 SS=0B61 CS=0B61 IP=0000 NV UP EI PL NZ NA PO NC
0B61:0000 B353 MOV BL,53
-U? ;查看程序代码
0B61:0000 B353 MOV BL,53
0B61:0002 B90800 MOV CX,0008
…...
0B61:0017 B44C MOV AH,4C
0B61:0019 CD21 INT 21
-D DS:0 L20? ;查看此时数据段内容 (程序段前缀 )
0B51:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 5A 05 8A 03
0B51:0010 5A 05 17 03 5A 05 49 05-01 01 01 00 02 FF FF FF
-U DS:0 L5? ;反汇编当前数据段内容 (程序段前缀 )
0B51:0000 CD20 INT 20
0B51:0002 FF9F009A CALL FAR [BX+9A00]
-
在 DEBUG下查看 ShowBL.exe的装入情况,
58
-R? ;查看当前寄存器内容
AX=0000 BX=0000 CX=001B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B51 ES=0B51 SS=0B61 CS=0B61 IP=0000 NV UP EI PL NZ NA PO NC
B353 MOV BL,53
- U CS:0? ;查看程序
0B61:0000 B353 MOV BL,53
0B61:0002 B90800 MOV CX,0008
0B61:0005 D0E3 SHL BL,1
0B61:0007 7205 JB 000E
…….
0B61:0017 B44C MOV AH,4C
0B61:0019 CD21 INT 21
…….
-G? ;执行程序
01010011
Program terminated normally
-
59
注意:
不能破坏程序段前缀内容,
否则无法返回 DOS,造成死机 。
讲义中介绍的第二种返回 DOS的方法 不作学习要求 。
(在老的教材或参考书中使用该法,新版的书中很少使用,
新版的教材 P98的例程可以不看,采用的是第二种方法 )。
想要掌握的同学可自学。
60
第二种 DOS返回方法,调用 20H类型的中断程序
◢ 20H 中断程序的功能:
处理程序结束,返回系统 。
◢ 调用 20H中断程序是有条件的:
要求当前的 CS应为程序段前缀在内存的段值问题:
如何保证执行到 INT 20H时,
当前 CS的值为程序段前缀在内存的段值?
xxxx,00 00 INT 20
61
采用下面的程序框架,
可保证执行 INT 20H时,
当前的 CS值为程序段前缀在内存的段值 。
code SEGMENT
ASSUME CS:code
main PROC FAR ;使 RET为远返回
start,PUSH DS ;入栈保存地址
MOV AX,0 ;程序段前缀的首地址
PUSH AX
、,;程序主体部分
、、
RET ;取程序段前缀首地址
main ENDP
code ENDS
END start
CD 20
xxxx
,、、
0000
xxxx,0
SS:S P
SS:S P
程序段前缀 P S P
PS P 的段值
PS P 的偏值用户程序
CS IP
62
注意:
1,不可在汇编语言程序的最后用 INT 20H返回 DOS。
原因是 20h中断子程的执行是有条件的 。
采用第二种返回 DOS的程序结构,才能满足该条件,
否则无法返回 。
2,不可在程序的最后用 INT 3返回 DOS。
原因是 3类型的中断子程实现断点设置,
只在 DEBUG下起作用 。
63
五,表达式及表达式中的操作符表达式
由常量,标号,变量和一些操作符构成 。
汇编程序对表达式进行运算后,得到一个确定的数值,
再把这个数值汇编到指令中 。
据表达式所表示的内容,分数字表达式,地址表达式 。
表达式是指令或伪操作的操作数 ;
表达式中的操作符由汇编程序完成例 MOV AX,12 - 4 ;MOV AX,8 ;数字表达式
LEA BX,[ string + 4 ] ;地址表达式
64
表达式中的操作符
▲ 有以下几类,
1,算术运算符 ( +,-,*,/,MOD )
2,逻辑运算符 ( AND,OR,NOT,XOR )
3,关系运算符 ( EQ,NE,GT,GE,LT,LE )
真,FFFFH; 假,0
4,数值返回操作符 ( SEG,OFFSET )
5,类型操作 ( PTR )
6,地址记数器 ( $ )
65
例,
1,算术运算符 ( +,-,*,/,MOD(取余数 ) )
MOV AX,6 * 8 ← MOV AX,48
2,逻辑运算符 (AND,OR,NOT,XOR)
MOV AX,80h OR 70h ← MOV AX,0F0h
3,关系运算符 ( EQ,NE,GT,GE,LT,LE )
真,FFFFH; 假,0
MOV AX,1 GE 2 ← MOV AX,0
66
4,数值返回操作符 ( SEG,OFFSET )
SEG 取符号地址的段地址例 MOV AX,SEG yy
OFFSET 取符号地址的偏移地址例 MOV BX,OFFSET yy
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
……,
cc ENDS
END start
67
aa SEGMENT
xx DB 'Hello!’
aa ENDS
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\>DEBUG hello1.exe
-U ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
MOV AX,bb
LEA DI,yy
68
注意,SEG,OFFSET只能对符号地址操作
MOV AX,SEG [BX]
MOV BX,OFFSET [SI]
69
汇编语言程序举例 (第三节例一 )
(实验二 编程任务 4)
编写完整汇编语言程序,完成内存数据块传送功能 。
将某段中的字符串,Hello!”传送到另一段中 。
70
例一 编写完整汇编语言程序,完成内存数据块传送功能 。
将某段中的字符串,Hello!”传送到另一段中 。
开始建立传送方向
DS,SI ← 源串首地址
ES,DI ←目的串首地址
CX ← 串长度串传送返回 D O S
利用变量定义字符串和缓冲区
71
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
MOV AH,4CH ;调用 4CH系统功能,返回 DOS
INT 21H
cc ENDS
END start ;指示程序结束和程序入口
72
D:\>EDIT hello.asm ;编写源程序
D:\>MASM hello ; ;汇编源程序
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
49860 + 421241 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK hello ; ;连接程序
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>hello ;执行程序
D:\>
警告性错误:无堆栈段此错误可忽略
73
D:\>DEBUG hello.exe? ;利用 DEBUG查看结果
-U? ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
-D 129D:0 L20? ;执行程序前,查看源串内容
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00,...............
-D 129E:0 L20? ;执行程序前,查看目的串
129E:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00,...............
129E:0010 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
-
CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET
yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
74
-G ; 执行程序
Program terminated normally
-D 129E,0 L20 ; 查看目的串
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129E:0010 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
-D 129D,0 L50 ; 从源串重新查看
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0010 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0020 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
129D:0030 00 00 B9 06 00 F3 A4 B4-4C CD 21 09 E8 08 00 03,.......L.!.....
129D:0040 F1 E8 03 00 3C 0D C3 AC-E8 EC F8 75 04 3C 3B 75,...<......u.<;u
-
75
问题思考,(实验课上讨论 )
1,一个段的大小为多少? 一定是 64K吗?
根据 DEBUG下查看的结果,
画出程序各段在内存的存放情况 。
2,假如将程序中的 MOV CX,6 改为 MOV CX,100H
程序执行的结果会如何? 试用 DEBUG观察结果 。
-U? ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
aa SEGMENT
xx DB 'Hello!’
aa ENDS
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
76
3,可否在程序结束处用一条 RET返回指令,返回 DOS?
(实验课上讨论 )
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
RET
cc ENDS
END start ;指示程序结束和程序入口
77
D:\>DEBUG hello.exe
- U
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[0000]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 F3 RET
129F:0018 43 INC BX
129F:0019 50 PUSH AX
129F:001A FF36C601 PUSH [01C6]
、、、
-
hello.exe
用户程序与用户程序相连的内存内容被看作程序时
78
4,END 语句后没有起始地址,程序执行的后果?
(实验课上讨论 )
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
MOV AH,4CH ;调用 4CH系统功能,返回 DOS
INT 21H
cc ENDS
END ; start ;指示程序结束和程序入口
79
5,如下操作为何查看不到结果?
(实验课上讨论 )
D:\>MASM hello; ;汇编源程序
D:\>LINK hello; ;连接程序
D:\>hello ;先在 DOS下运行程序
D:\>DEBUG ;再进入 DEBUG查看结果
- D 129E:0 L30 ;查看目的串
129E:0000 2A 75 05 80 0E 2D DA 02-3A 06 14 D4 75 C9 4E 32 *u...-..:...u.N2
129E:0010 C0 86 04 46 3C 0D 75 02-88 04 89 36 EB D8 89 0E,..F<.u....6....
129E:0020 E9 D8 C3 BE CE DC 8B 4C-05 8B 74 09 E8 08 00 03,......L..t.....
-D 129D:0 L30 ;查看源串
129D:0000 75 04 FE 06 29 DA 3C 3F-75 05 80 0E 2D DA 02 3C u...).<?u...-..<
129D:0010 2A 75 05 80 0E 2D DA 02-3A 06 14 D4 75 C9 4E 32 *u...-..:...u.N2
129D:0020 C0 86 04 46 3C 0D 75 02-88 04 89 36 EB D8 89 0E,..F<.u....6....
80
data1 SEGMENT ;数据段 1,(可据需要设定,也可无 )
…… ;变量定义
data1 ENDS
data2 SEGMENT ;数据段 2 (可据需要设定,也可无 )
……
data2 ENDS
code SEGMENT ;程序段
ASSUME CS,code,DS:data1,ES:data2
start:,、,;程序主体部分
、、、
、、、
、、、
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
完整汇编语言程序框架:
第三章 汇编语言程序设计第一节 汇编语言上机过程第二节 汇编语言程序结构第三节 指示性语句第四节 汇编语言程序举例第五节 BIOS和 DOS功能调用第六节 汇编语言程序设计
2
作业,3-2,3-6,3-7,3-9,3-12
复习内容,P97--P114
预习内容,P114-P140
P145-147(不作要求,自学)
3
上机环境硬件系统软件应用软件操作系统,DOS系统编辑器,EDIT.exe
编程序,MASM.exe
连接程序,LINK.exe
调试程序,DEBUG.exe
用户开发的程序,ABC.exe等
CPU、存储器 (ROM,RAM),I/O接口、输入、输出设备
4
第一节 汇编语言上机过程
D:>EDIT ABC.asm
D:>MASM ABC;
有语法错,回 EDIT下改该程序
D:>LINK ABC;
有错,回在 EDIT下改程序
D:>ABC
运行结果错,回 EDIT下改程序或在 DEBUG下调试,找原因 。
D:>DEBUG ABC.exe
编辑源程序 EDIT ABC.ASM
汇编源程序 MASM ABC.ASM
形成目标程序 ABC.OBJ
连接目标程序 LINK ABC.OBJ
有连接错误信息?
形成可执行程序 ABC.EXE
装入可执行程序到内存,并执行
D:\>sub>ABC
下一程序用 DEBUG 调试可执行程序
D:\>sub>DEBUG ABC.EXE 找到原因
Y
N
Y
N
N
Y
N
有汇编错误信息?
Y运行结果正确?
用 DEBUG调试程序查错?
5
第二节 汇编语言程序结构一,程序结构二,语句结构
6
汇编语言程序结构例一程序,movs.asm
功能,实现数据传送功能数据段 1 传送到 数据段 2
目的,学习程序结构
7
一,程序结构
程序由数条语句构成,每条语句占一行 。
指令性语句 (指令语句 )
指示性语句 (伪指令语句 )
分段结构程序按段编写,与 8088内存分段编址相对应 。
每段由伪操作 SEGMENT开始,由 ENDS结束 。
程序最后为 END结束语句,后跟一启动地址 。
启动地址指示程序开始执行的第一条语句 。
程序中设有返回 DOS的功能 。
使程序执行完后返回 DOS系统的命令接受状态 。
程序中用到内存操作数时,
应按操作数的寻址方式,给相应的段寄存器赋值;汇编语言程序结构例一 movs.asm;实现数据传送功能
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,SEG str2
MOV ES,AX
MOV DI,OFFSET str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H ;返回 DOS
cc ENDS
END start ;指示程序结束
8
汇编语言程序结构例二程序,scans.asm (子程结构)
子程内容,用二进制显示 BX内容功能,实现用二进制显示中断向量表中 ( 0,0~0,3FFH)
数据 D0H的个数目的,了解程序可由多个段构成
9
程序可由多个段构成,至少有一个代码段;汇编语言程序结构例二 ( 子程结构 ) scans.asm;用二进制显示中断向量表中 ( 0,0~0,3FFH) 数据 D0H的个数
key EQU 0D0H ;用符号表示常量 (关键字 )
code SEGMENT ;代码段开始
ASSUME CS:code
begin,MOV AX,0000H
MOV DS,AX
MOV SI,0000H
MOV CX,0400H
MOV BX,0
MOV AL,key
next,CMP [ SI ],AL
JNZ point
INC BX
point,INC SI
LOOP next
CALL display ; 调用显示子程
MOV AH,4CH ; 返回 DOS
INT 21H;用二进制显示 BX内容子程
display PROC
MOV CX,16
rotate,ROL BX,1
MOV DL,BL
AND DL,01H
ADD DL,30H
MOV AH,2H
INT 21H
LOOP rotate
RET ;子程返回
display ENDP
code ENDS ;代码段结束
END begin ;指示程序结束和;程序入口
10
二、语句结构
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
data SEGMENT ;数据段
var DB?
data ENDS
code SEGMENT ;代码段
ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV var,CL
MOV AH,4CH
INT 21H ;返回 DOS
code ENDS
END start
例:
11
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
1,名字项
据语句功能的不同,
名字项可用来表示,
段名,变量名,
标号,过程名以及常量名 等 。
data SEGMENT ; 数据段
var DB?
data ENDS
code SEGMENT ;代码段
ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV var,CL
MOV AH,4CH
INT 21H ;返回 DOS
code ENDS
END start
12
名字项用一个符号表示。
对符号的规定,
① 由字符 A~Z,a~z,0~9及符号 @,$、下划线 _ 等组成,
最长 31个字符,超出部分忽略。
② 不能用数字打头,以免与十六进制数相混。
③ 不使用汇编程序中的保留字。 (如指令的助记符等 )
④ 对定义的符号不区分大小写。
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
13
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
2,助记符项助记符可以是指令,伪操作中的助记符 。
对于指令,汇编程序将其翻译成机器语言指令。
MOV AX,100 → B8 00 01
对于伪操作,汇编程序据其要求的功能进行处理。
data SEGMENT → data与一段值对应
string DB ‘Tsinghua’ → string与一内存地址对应
14
3,操作数项
操作数给出参与操作的数或数所在的地方 。
操作数多于一个时,用逗号分开 。
操作数可以是 常数,寄存器,存储器操作数,
标号名,过程名或 表达式 等 。
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
15
常数给出具体的数据 。 可以是数字常量或字符常量 。
◢ ◢ 数字默认十进制,也可加 D表示十进制数 。 如 1234D,1234
◢ ◢ 数字后加 B表示二进制数 。 如 1010B
◢ ◢ 数字后加 H表示十六进制数 。 如 1234H
◢ ◢ 字符常量,用单引号表示 。 如 ‘ 1234’
汇编时,用字符对应的 ASCII表示 。 如 31H,32H,33H,34H
例 data1 DB 12,34,56 ;十进制
data2 DB 12H,34H,56H ;十六进制
MOV AL,‘G’ ;字符
string DB ‘1234’ ;字符串
16
A,B,C,D,E,F开头的十六进制数前面加 0,
与 H结尾的标识符区别 。
如 寄存器名 AH,BH,CH,DH
变量名 abcdH 等例 mov AL,0AH
mov AL,AH
mov BX,0abcdH
17
4,注释项
由分号引出,用来说明语句或程序的功能 。
汇编程序对分号后的内容不做处理 。
作用,① 注释程序,增强程序可读性 。
② 可放在语句最前,暂时注释某语句,调试程序用 。
例,、、; MOV AH,2 ;显示提示信息; MOV DL,’A’; INT 21H
、、、
[ 名字 ] [,] 助记符 [ 操作数,] [ ;注释 ]
名字项 助记符项 操作数项 注释项
18
第三节 指示性语句 / 第四节 汇编语言程序举例一,程序开始和结束二,段定义三,变量定义四,ASSUME语句
汇编语言程序 举例一了解 DOS的返回,装入功能五,表达式及表达式中的操作符
汇编语言程序例二六,过程定义 (第五节程序设计介绍 )
七,等值定义 (第五节程序设计介绍 )
汇编语言程序例三 (第五节程序设计介绍 )
19
指示性语句与指令性语句:
指令性语句 是用指令系统中的指令构成的语句 。
例 MOV AX,BX
指示性语句 是指示汇编程序进行汇编的操作 。
例 MOV AX,4 + 8 中的 +
code SEGMENT 中的 SEGMENT
MOV BX,OFFSET string 中的 OFFSET
20
指示性语句与指令性语句区别一个程序经汇编,连接和装入内存后,在执行程序之前:
◢ 指示性语句的功能已经完成,故又称伪操作 。
◢ 而指令性语句的功能尚未完成,需控制 CPU去执行,才能完成 。
21
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,bb
MOV ES,AX
LEA DI,str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello2.exe
-U,查看代码段
12A0:0000 FC CLD
12A0:0001 B89E12 MOV AX,129E
12A0:0004 8ED8 MOV DS,AX
12A0:0006 8D360000 LEA SI,[0000]
12A0:000AB89F12 MOV AX,129F
12A0:000D 8EC0 MOV ES,AX
12A0:000F 8D3E0000 LEA DI,[0000]
12A0:0013 B90600 MOV CX,0006
12A0:0016 F3 REPZ
12A0:0017A4 MOVSB
12A0:0018 B44C MOV AH,4C
12A0:001ACD21 INT 21
、、、
-D 129E:0 L10 ;查看数据段 1的内容
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00
Hello!..........
-D 129F:0 L10 ;查看数据段 2的内容
129F:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
数据传送源程序 hello2.asm 程序经汇编、连接后,装入内存的情况如下:
22
常用伪操作介绍一,程序开始和结束二,段定义三,变量定义四,ASSUME语句五,表达式中的操作符六,过程定义七,等值定义
23
一,模块定义和程序结束伪操作
1,NAME 和 TITLE 伪操作格式 NAME 模块名格式 TITLE 模块名
▲ 在源程序开始可用 NAME 或 TITLE 为模块命名,
模块名的作用是指示给连接程序进行连接用 。
▲ 源程序中可无模块定义,此时源文件名作为模块名 。
24
2,END伪操作格式 END 启动地址
▲ 作用是指示源程序到此结束 。
汇编程序对 END 之后的语句不进行处理 。
程序中所有有效语句应放在 END 语句之前 。
▲ 源程序中必须有 END 结束语句 。
汇编程序对无 END 语句的源程序不进行处理,
只给出无 END 语句错误信息 。
25
假设 TEST.asm 是一个无 END 语句的汇编语言源程序 。
其汇编结果如下,
D:\ MASM TEST;↙
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
End of file encountered on input file
End of file encountered on input file
49968 + 421181 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\
由于没有 END语句,汇编程序根本没对源程序进行汇编,
此时显示警告性错误总数为 0,严重性错误总数为 0,
用户不要被此值的误导 。
26
▲ 启动地址可是一个标号或过程名,指示程序的入口 。
程序装入内存后,系统跳转到入口处,开始执行程序 。
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,SEG str2
MOV ES,AX
MOV DI,OFFSET str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello.exe
-U,查看代码段
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[0000]
129F:000AB89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000FBF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、
-D 129d:0 l10 ;查看数据段 1的内容
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00
00 Hello!..........
-D 129e:0 l10 ;查看数据段 2的内容
129E:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
27
二,段定义伪操作格式 段名 SEGMENT
、、、
、、、
段名 ENDS
▲ 段定义由伪操作 SEGMENT开始,ENDS结束 。
其中,SEGMENT 和 ENDS 必须成对出现,
且语句前必须有段名,段名必须相同 。
▲ SEGMENT和 ENDS语句之间可以有指令和其他伪操作,
表示存放在该段内存的变量,指令或其他伪操作对该段内存的处理
▲ 程序中可以定义多个段 。
▲ 程序经汇编,连接及装入内存后,段名为一具体的段值 。
28
aa SEGMENT ;数据段 1
str1 DB 'Hello!’
aa ENDS
bb SEGMENT ;数据段 2
str2 DB 6 dup (?)
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc
ASSUME DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,str1
MOV AX,bb
MOV ES,AX
LEA DI,str2
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\masm>DEBUG hello2.exe
-U,查看代码段
12A0:0000 FC CLD
12A0:0001 B89E12 MOV AX,129E
12A0:0004 8ED8 MOV DS,AX
12A0:0006 8D360000 LEA SI,[0000]
12A0:000AB89F12 MOV AX,129F
12A0:000D 8EC0 MOV ES,AX
12A0:000F 8D3E0000 LEA DI,[0000]
12A0:0013 B90600 MOV CX,0006
12A0:0016 F3 REPZ
12A0:0017A4 MOVSB
12A0:0018 B44C MOV AH,4C
12A0:001ACD21 INT 21
、、、
-D 129E:0 L10 ;查看数据段 1的内容
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00
Hello!..........
-D 129F:0 L10 ;查看数据段 2的内容
129F:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00
................
-
数据传送源程序,程序经汇编、连接后,装入内存的情况如下:
29
三,变量定义伪操作格式 变量名 类型助记符 操作数 [,操作数,..,]
▲ 用来定义程序中所用的内存操作数 。
其中 变量名 指示内存操作数的地址 ( 符号地址 )
类型助记符 指示内存操作数的类型 (字节,字,双字等 )
操作数 指示内存操作数的内容
▲ 汇编程序将定义的操作数,按其类型分配内存单元数,
顺序存入变量名指向的内存单元中 。
▲ 常用的类型助记符有:
DB 指示其后的操作数为字节类型
DW 指示其后的操作数为字类型
DD 指示其后的操作数为双字类型
30
例 1,定义赋初值的变量
data SEGMENT
xx DB 1,-1,0fcH
yy DW 1,-1,0fcH
zz DD 1,- 1,0fcH
data ENDS
xx
yy
zz
01
FF
FC
01
00
FF
FF
FC
00
01
00
00
00
FF
FF
FF
FF
FC
00
00
00
1
- 1
FC
1
- 1
FC
1
- 1
FC
31
例 2,定义字符串变量 ( 只能用 DB定义 )
data SEGMENT
str1 DB ' TsingHua '
str2 DB 'INPUT:',0dH,0aH,'$'
data ENDS
注意,3个及其以上的字符,
只能用 DB定义
str1 DW ‘abcd’
str2 DD ‘abcd’
str1
str2
54
73
69
6e
67
48
75
61
49
4e
50
55
54
3a
0d
0a
24
‘T’
‘s’
‘i’
‘n’
‘g’
‘H’‘u’
‘a’
‘I’
‘N’
‘P’
‘U’
‘T’
‘:’0dH
0aH
‘$’
32
▲ 操作数可以是用 常量,表达式和? 表示 。
常量和表达式 表示内存操作数的初始值,
其值应在其定义的类型范围内,否则汇编出错 。
例 aa DB 270
bb DW 80000
用? 表示不置初始值的内存操作数 。
例 cc DB?
可用 DUP 复制操作符 定义相同的操作数,其格式为重复次数 DUP( 操作数 )
例 ee DB 3 DUP ( 4 )
等价于 ee DB 4,4,4
33
data SEGMENT
xx DB 1,-1,0FCH
yy DW 1,- 1,0FCH
zz DD 1,-1,0FCH
str DB 'TsingHua'
buf DB 4,?,4 DUP (?)
DB ‘dataend’
data ENDS
code SEGMENT
ASSUME CS:code
ASSUME DS:data
start,MOV AX,data
MOV DS,AX
LEA BX,xx
LEA SI,yy
LEA DI,zz
MOV AH,4CH
INT 21H
code ENDS
END start
D:\ MA SM > D E B UG v ari ble,e xe
- U
12A 1:0 000 B 8 9E 12 MO V AX,129E
12A 1:0 003 8 E D8 MO V DS,AX
12A 1:0 005 8 D 1E 000 0 LEA BX,[0000]
12A 1:0 009 8 D 360 300 LEA SI,[0003 ]
12A 1:0 00 D 8 D 3E 090 0 LEA DI,[0009]
12A 1:0 01 1 8 D 1E 150 0 LEA BX,[0015]
12A 1:0 015 8 D 361 D0 0 LEA SI,[001D]
12A 1:0 019 B 4 4C MO V AH,4C
12A 1:0 01B C D2 1 INT 21
12A 1:0 01 D F F 362 43E PUSH [3E2 4]
-D 1 29E,0 L 30
129E,0 000 01 F F FC 0 1 0 0 F F F F F C-00 0 1 00 00 0 0 F F F F F F,.,..,..,..,,..,
129E,0 010 FF FC 00 0 0 0 0 5 4 73 69 -6E 6 7 4 8 7 5 6 1 0 4 0 0 00,.,.,T singH ua,..
129E,0 020 00 0 0 0 0 6 4 6 1 74 61 65 -6E 6 4 00 0 0 0 0 00 0 0 00,.,d atae nd...,..
129E,0 030 B8 9E 12 8E D8 8D 1 E 0 0-00 8D 3 6 0 3 00 8 D 3E 09,..,..,..,6..,>.
-
xx
yy
zz
str buf
‘d a t a e n d’
段名 d a t a
变量 xx
变量 yy
变量 zz
变量 s tr
变量 b u f
例 4,在 DEBUG下查看变量存放情况。
34
四,ASSUME伪操作格式 ASSUME 段寄存器:段名 [,段寄存器,段名,… ]
其中 段寄存器 为 CS,DS,ES,SS中的一个段名 为用伪操作 SEGMENT定义过的段名例 ASSUME CS,cc,DS:aa
▲ ASSUME 伪操作的作用指示汇编程序指令中用到的标号,过程及变量所在的段 。
其中 对标号,过程必须用 CS 段寄存器指示对变量可用 CS,DS,ES,SS段寄存器指示
35
▲ 若未用 ASSUME语句指示指令中用到的标号,
过程和变量所在的段,汇编程序将给出错误信息 。
▲ ASSUME语句只起指示作用,并无实际的操作 。
在程序中引用定义的变量做内存操作数时,
需按寻址方式用传送指令 ( 如 MOV) 给相应的段寄存器赋值 。
36
例 用程序实现 1234H + 5678H
va lu e
r esu lt
34
12
78
56
00
00
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值
MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
37
注释掉 ASSUME语句,其汇编结果:
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT; ASSUME CS:code,DS:data
start,MOV AX,data
MOV DS,AX
MOV AX,value
ADD AX,value+2
MOV result,AX
MOV AH,4CH
INT 21H
code ENDS
END start
D:\MASM>MASM assume;
Microsoft (R) MacroAssembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights
reserved.
assume.ASM(8),Missing or unreachable CS
assume.ASM(10),Cannot address with segment register
assume.ASM(11),Cannot address with segment register
assume.ASM(12),Cannot address with segment register
49872 + 421341 Bytes symbol space free
0 Warning Errors
4 Severe Errors
D:\MASM>
38
程序中有 ASSUME语句,经汇编,连接和装入内存后的情况:
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值
MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
D:\MASM>DEBUG assume.exe
-R ;查看程序执行前各寄存器
AX=0000 BX=0000 CX=0023 DX=0000
SP=0000 BP=0000 SI=0000 DI=0000
DS=1295 ES=1295 SS=12A5
CS=12A6 IP=0000
NV UPEI PL NZ NA PO NC
12A6:0000 B8A512 MOV AX,12A5
-U ;查看在内存的程序
12A6:0000 B8A512 MOV AX,12A5
12A6:0003 8ED8 MOV DS,AX
12A6:0005A10000 MOV AX,[ 0000 ]
12A6:0008 03060200 ADD AX,[ 0002 ]
12A6:000CA30400 MOV [ 0004 ],AX
12A6:000F B44C MOV AH,4C
12A6:0011 CD21 INT 21
、、、、、
-注意:
程序装入内存后,执行程序前,
当前的 DS值并非程序定义的 data段值,1295 不等于 12A5
39
思考,如果上例中没有 MOV DS,AX 程序执行的结果会怎样?
D:\MASM>DEBUG assume.exe
-R ;查看程序执行前各寄存器
AX=0000 BX=0000 CX=0023 DX=0000
SP=0000 BP=0000 SI=0000 DI=0000
DS=1295 ES=1295 SS=12A5 CS=12A6 IP=0000
NV UPEI PL NZ NA PO NC
12A6:0000 B8A512 MOV AX,12A5
-U ;查看在内存的程序
12A6:0000 B8A512 MOV AX,12A5
12A6:0003A10000 MOV AX,[ 0000 ]
12A6:0006 03060200 ADD AX,[ 0002 ]
12A6:000AA30400 MOV [ 0004 ],AX
12A6:000D B44C MOV AH,4C
12A6:000F CD21 INT 21
、、、、、
data SEGMENT
value DW 1234H,5678H
result DW?
data ENDS
code SEGMENT
ASSUME CS:code,DS:data
start,MOV AX,data ;给 DS赋值; MOV DS,AX
MOV AX,value ;取数
ADD AX,value+2 ;两数相加
MOV result,AX ;保存结果
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
40
结论:
1,ASSUME语句只起指示作用,没有赋值作用
2,程序中用到内存操作数时,
应按操作数的寻址方式,给相应的段寄存器赋值 。
41
第三节 指示性语句 / 第四节 汇编语言程序举例一,程序开始和结束二,段定义三,变量定义四,ASSUME语句
汇编语言程序 举例一了解 DOS的返回,装入功能五,表达式及表达式中的操作符
汇编语言程序例二六,过程定义 (第五节程序设计介绍 )
七,等值定义 (第五节程序设计介绍 )
汇编语言程序例三 (第五节程序设计介绍 )
42
汇编语言程序 举例一
43
例 将 BL寄存器的内容按二进制形式显示出来
1 0 1 0 0 1 1 0(BL)
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
、、、
31 30 31 30 30 31 31 30
44
code SEGMENT
ASSUME CS,code
start:
...
...
...
...
code ENDS
END start
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
45
D:\>MASM SBL;? 汇编成 ShowBL.obj
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
48912 + 447243 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK SBL;? 连接成 ShowBL.exe
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>SBL? 装载并执行 ShowBL.exe
请猜想执行的结果?
46
D:\>DEBUG SBL.exe? ;用 DEBUG装入程序
-U?
0B5E:0000 B90800 MOV CX,0008
0B5E:0003 D0E3 SHL BL,1
0B5E:0005 7205 JB 000C
0B5E:0007 B230 MOV DL,30
0B5E:0009 EB03 JMP 000E
0B5E:000B 90 NOP
0B5E:000C B231 MOV DL,31
0B5E:000E B402 MOV AH,02
0B5E:0010 CD21 INT 21
0B5E:0012 49 DEC CX
0B5E:0013 75EE JNZ 0003
0B5E:0015 09E8 OR AX,BP
0B5E:0017 96 XCHG SI,AX
0B5E:0018 00F8 ADD AL,BH
0B5E:001A B262 MOV DL,62
0B5E:001C FFFF DI
0B5E:001D EB0A JMP 0029
-
hello.exe
用户程序与用户程序相连的内存内容被看作程序时死机
47
▲ 复习 DOS系统的启动过程执行用户程序后,
若要返回 DOS状态,
即在屏幕上出现 DOS提示符,
等待输入新的命令,
应在用户程序的最后安排完成此功能的程序段 。
FF FF,0000 H
1
2
4
3
ROM
系统检测程序
IO,SY S 模块
COM MAN D,CO M
MS DOS,SY S 模块用户程序空 间引导程序
1K B 中断向量表
RA M
内 存
ROM BIO S
DO S
IO,SY S
COM MAN D,CO M
MS DOS,SY S
引导程序磁 盘
EDIT,EX E
MA SM,EX E
LINK,E XE
DE BUG.e x e
应用程序其他系统程序
he llo,asm
he llo,obj
he llo,exe
通常采用调用
DOS 系统功能完成 。
48
调用 DOS系统的 4CH 功能,返回 DOS
方法,在要返回 DOS 处,安排指令:
MOV AH,4CH
INT 21H
执行完 4CH的功能调用,即返回 DOS 。
例 code SEGMENT
ASSUME CS,code
start:,、,;程序主体部分
、、、
、、、
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
49
code SEGMENT
ASSUME CS,code
start:
...
...
...
...
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
MOV CX,8 ;显示字符个数为 8
next,SHL BL,1 ;将显示位移至 CF中
JC one ;CF=1?
MOV DL,30H ;CF=0,将 0的 ASCII放在 DL中
JMP exit
one,MOV DL,31H ;CF=1,将 1的 ASCII放在 DL中
exit,MOV AH,2
INT 21H ;调用 DOS功能显示
DEC CX ;循环次数减 1
JNZ next ;判断是否结束
MOV BL,53H ;设置一个测试 53h
50
D:\>MASM ShowBL; 汇编成 ShowBL.obj
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
48912 + 447243 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK ShowBL; 连接成 ShowBL.exe
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>ShowBL 装载并执行 ShowBL.exe
01010011
D:\masm>
51
D:\>DEBUG ShowBL.exe? ;用 DEBUG装入程序
-U?
0B5E:0000 B90800 MOV CX,0008
0B5E:0003 D0E3 SHL BL,1
0B5E:0005 7205 JB 000C
0B5E:0007 B230 MOV DL,30
0B5E:0009 EB03 JMP 000E
0B5E:000B 90 NOP
0B5E:000C B231 MOV DL,31
0B5E:000E B402 MOV AH,02
0B5E:0010 CD21 INT 21
0B5E:0012 49 DEC CX
0B5E:0013 75EE JNZ 0003
0B5F:0015 B44C MOV AH,4C
0B5F:0017 CD21 INT 21
-
52
code SEGMENT
ASSUME CS,code
start:
… ;程序主体部分
...
...
...
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
一个完整汇编程序的基本框架,
53
DOS的装入功能 (又称 EXEC系统功能 )
可执行文件,exe,应装入内存方能执行 。
由 DOS的装入功能完成 。
在 DOS的提示符后输入可执行文件的文件名,
按回车键,DOS系统即调用装入功能,
将可执行程序装入内存 。
54
内 存
256K B RO M
000 0,0000H
004 0,0000H
A000:0000H
C800:0000H
FE00:0000H
FE00:1FFF H
640K B R AM
基本内存显示器显示缓存区
ROM BIO S
系统检测程序
IO,SY S 模块
CO MMAND,CO M 常驻 模块
MS DOS,SY S 模块用户程序空间
CO MMAND,CO M 暂驻 模块
DO S 工作区
BIO S 工作区
1K B 中断向量表
128K B R AM
保留区
DO S
其他系统程序磁 盘应用程序
IO,SY S
COM MAN D,CO M
MS DOS,SY S
引导程序
EDIT,EX E
MA SM,EX E
LINK,E XE
DE BUG.e x e
hel lo.asm
hel lo.o bj
hel lo.e xe
sc ans.asm
sc ans.obj
sc ans.e xe
55
完成以下操作:
确定内存可用部分,
以便存放要执行的,exe 文件。
建立程序段前缀 PSP
( Program Segment Prefix)
◢ 程序段前缀大小 100H,
即 256个字节。
◢ 存放进程间的控制信息。
◢ PSP最开始的两个字节 CD 20,
是一条 INT 20H指令。
装入可执行程序,exe
000 0,0 000H
可用内存空间内 存
FF FF,0 00 0 H
ROM BIO S
系统检测程序
COM M AN D,COM
DO S 系统
1K B 中断向量表
CD 20
,、、
,、、
,、、
hel lo,exe
xxx x,0 000H
xxx x,0 0FFH
程序段前缀用户程序
DOS的装入功能
56
修改以下寄存器的值
◢ DS,ES设置为程序段前缀所在内存的段值;
(DS)=xxxxH
(ES)=xxxxH
◢ SS,SP设置为由连接程序传过来的值;
◢ CS,IP设置为程序的入口地址,
即伪操作 END后跟的符号名对应的物理地址;
此时 CS:IP 指向用户程序,
开始执行用户程序 。
000 0,0 000H
可用内存空间内 存
FF FF,0 00 0 H
ROM BIO S
系统检测程序
COM M AN D,COM
DO S 系统
1K B 中断向量表
CD 20
,、、
,、、
,、、
hel lo,exe
xxx x,0 000H
xxx x,0 0FFH
程序段前缀
CS,I P
57
D:\>DEBUG ShowBL.exe
-R? ;查看当前寄存器内容
AX=0000 BX=0000 CX=001B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B51 ES=0B51 SS=0B61 CS=0B61 IP=0000 NV UP EI PL NZ NA PO NC
0B61:0000 B353 MOV BL,53
-U? ;查看程序代码
0B61:0000 B353 MOV BL,53
0B61:0002 B90800 MOV CX,0008
…...
0B61:0017 B44C MOV AH,4C
0B61:0019 CD21 INT 21
-D DS:0 L20? ;查看此时数据段内容 (程序段前缀 )
0B51:0000 CD 20 FF 9F 00 9A F0 FE-1D F0 4F 03 5A 05 8A 03
0B51:0010 5A 05 17 03 5A 05 49 05-01 01 01 00 02 FF FF FF
-U DS:0 L5? ;反汇编当前数据段内容 (程序段前缀 )
0B51:0000 CD20 INT 20
0B51:0002 FF9F009A CALL FAR [BX+9A00]
-
在 DEBUG下查看 ShowBL.exe的装入情况,
58
-R? ;查看当前寄存器内容
AX=0000 BX=0000 CX=001B DX=0000 SP=0000 BP=0000 SI=0000 DI=0000
DS=0B51 ES=0B51 SS=0B61 CS=0B61 IP=0000 NV UP EI PL NZ NA PO NC
B353 MOV BL,53
- U CS:0? ;查看程序
0B61:0000 B353 MOV BL,53
0B61:0002 B90800 MOV CX,0008
0B61:0005 D0E3 SHL BL,1
0B61:0007 7205 JB 000E
…….
0B61:0017 B44C MOV AH,4C
0B61:0019 CD21 INT 21
…….
-G? ;执行程序
01010011
Program terminated normally
-
59
注意:
不能破坏程序段前缀内容,
否则无法返回 DOS,造成死机 。
讲义中介绍的第二种返回 DOS的方法 不作学习要求 。
(在老的教材或参考书中使用该法,新版的书中很少使用,
新版的教材 P98的例程可以不看,采用的是第二种方法 )。
想要掌握的同学可自学。
60
第二种 DOS返回方法,调用 20H类型的中断程序
◢ 20H 中断程序的功能:
处理程序结束,返回系统 。
◢ 调用 20H中断程序是有条件的:
要求当前的 CS应为程序段前缀在内存的段值问题:
如何保证执行到 INT 20H时,
当前 CS的值为程序段前缀在内存的段值?
xxxx,00 00 INT 20
61
采用下面的程序框架,
可保证执行 INT 20H时,
当前的 CS值为程序段前缀在内存的段值 。
code SEGMENT
ASSUME CS:code
main PROC FAR ;使 RET为远返回
start,PUSH DS ;入栈保存地址
MOV AX,0 ;程序段前缀的首地址
PUSH AX
、,;程序主体部分
、、
RET ;取程序段前缀首地址
main ENDP
code ENDS
END start
CD 20
xxxx
,、、
0000
xxxx,0
SS:S P
SS:S P
程序段前缀 P S P
PS P 的段值
PS P 的偏值用户程序
CS IP
62
注意:
1,不可在汇编语言程序的最后用 INT 20H返回 DOS。
原因是 20h中断子程的执行是有条件的 。
采用第二种返回 DOS的程序结构,才能满足该条件,
否则无法返回 。
2,不可在程序的最后用 INT 3返回 DOS。
原因是 3类型的中断子程实现断点设置,
只在 DEBUG下起作用 。
63
五,表达式及表达式中的操作符表达式
由常量,标号,变量和一些操作符构成 。
汇编程序对表达式进行运算后,得到一个确定的数值,
再把这个数值汇编到指令中 。
据表达式所表示的内容,分数字表达式,地址表达式 。
表达式是指令或伪操作的操作数 ;
表达式中的操作符由汇编程序完成例 MOV AX,12 - 4 ;MOV AX,8 ;数字表达式
LEA BX,[ string + 4 ] ;地址表达式
64
表达式中的操作符
▲ 有以下几类,
1,算术运算符 ( +,-,*,/,MOD )
2,逻辑运算符 ( AND,OR,NOT,XOR )
3,关系运算符 ( EQ,NE,GT,GE,LT,LE )
真,FFFFH; 假,0
4,数值返回操作符 ( SEG,OFFSET )
5,类型操作 ( PTR )
6,地址记数器 ( $ )
65
例,
1,算术运算符 ( +,-,*,/,MOD(取余数 ) )
MOV AX,6 * 8 ← MOV AX,48
2,逻辑运算符 (AND,OR,NOT,XOR)
MOV AX,80h OR 70h ← MOV AX,0F0h
3,关系运算符 ( EQ,NE,GT,GE,LT,LE )
真,FFFFH; 假,0
MOV AX,1 GE 2 ← MOV AX,0
66
4,数值返回操作符 ( SEG,OFFSET )
SEG 取符号地址的段地址例 MOV AX,SEG yy
OFFSET 取符号地址的偏移地址例 MOV BX,OFFSET yy
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
……,
cc ENDS
END start
67
aa SEGMENT
xx DB 'Hello!’
aa ENDS
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
D:\>DEBUG hello1.exe
-U ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
MOV AX,bb
LEA DI,yy
68
注意,SEG,OFFSET只能对符号地址操作
MOV AX,SEG [BX]
MOV BX,OFFSET [SI]
69
汇编语言程序举例 (第三节例一 )
(实验二 编程任务 4)
编写完整汇编语言程序,完成内存数据块传送功能 。
将某段中的字符串,Hello!”传送到另一段中 。
70
例一 编写完整汇编语言程序,完成内存数据块传送功能 。
将某段中的字符串,Hello!”传送到另一段中 。
开始建立传送方向
DS,SI ← 源串首地址
ES,DI ←目的串首地址
CX ← 串长度串传送返回 D O S
利用变量定义字符串和缓冲区
71
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
MOV AH,4CH ;调用 4CH系统功能,返回 DOS
INT 21H
cc ENDS
END start ;指示程序结束和程序入口
72
D:\>EDIT hello.asm ;编写源程序
D:\>MASM hello ; ;汇编源程序
Microsoft (R) Macro Assembler Version 5.10
Copyright (C) Microsoft Corp 1981,1988,All rights reserved.
49860 + 421241 Bytes symbol space free
0 Warning Errors
0 Severe Errors
D:\>LINK hello ; ;连接程序
Microsoft (R) Overlay Linker Version 3.61
Copyright (C) Microsoft Corp 1983-1987,All rights reserved.
LINK,warning L4021,no stack segment
D:\>hello ;执行程序
D:\>
警告性错误:无堆栈段此错误可忽略
73
D:\>DEBUG hello.exe? ;利用 DEBUG查看结果
-U? ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
-D 129D:0 L20? ;执行程序前,查看源串内容
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00,...............
-D 129E:0 L20? ;执行程序前,查看目的串
129E:0000 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00,...............
129E:0010 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
-
CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET
yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
74
-G ; 执行程序
Program terminated normally
-D 129E,0 L20 ; 查看目的串
129E:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129E:0010 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
-D 129D,0 L50 ; 从源串重新查看
129D:0000 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0010 48 65 6C 6C 6F 21 00 00-00 00 00 00 00 00 00 00 Hello!..........
129D:0020 FC B8 9D 12 8E D8 8D 36-00 00 B8 9E 12 8E C0 BF,......6........
129D:0030 00 00 B9 06 00 F3 A4 B4-4C CD 21 09 E8 08 00 03,.......L.!.....
129D:0040 F1 E8 03 00 3C 0D C3 AC-E8 EC F8 75 04 3C 3B 75,...<......u.<;u
-
75
问题思考,(实验课上讨论 )
1,一个段的大小为多少? 一定是 64K吗?
根据 DEBUG下查看的结果,
画出程序各段在内存的存放情况 。
2,假如将程序中的 MOV CX,6 改为 MOV CX,100H
程序执行的结果会如何? 试用 DEBUG观察结果 。
-U? ;查看程序代码
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[ 0000 ]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 B44C MOV AH,4C
129F:0019 CD21 INT 21
、、、、、、
aa SEGMENT
xx DB 'Hello!’
aa ENDS
bb SEGMENT
yy DB 6 dup (?)
bb ENDS
cc SEGMENT
ASSUME CS:cc,DS:aa,ES:bb
start,CLD
MOV AX,aa
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6
REP MOVSB
MOV AH,4CH
INT 21H
cc ENDS
END start
76
3,可否在程序结束处用一条 RET返回指令,返回 DOS?
(实验课上讨论 )
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
RET
cc ENDS
END start ;指示程序结束和程序入口
77
D:\>DEBUG hello.exe
- U
129F:0000 FC CLD
129F:0001 B89D12 MOV AX,129D
129F:0004 8ED8 MOV DS,AX
129F:0006 8D360000 LEA SI,[0000]
129F:000A B89E12 MOV AX,129E
129F:000D 8EC0 MOV ES,AX
129F:000F BF0000 MOV DI,0000
129F:0012 B90600 MOV CX,0006
129F:0015 F3 REPZ
129F:0016 A4 MOVSB
129F:0017 F3 RET
129F:0018 43 INC BX
129F:0019 50 PUSH AX
129F:001A FF36C601 PUSH [01C6]
、、、
-
hello.exe
用户程序与用户程序相连的内存内容被看作程序时
78
4,END 语句后没有起始地址,程序执行的后果?
(实验课上讨论 )
aa SEGMENT ; 数据段 1
xx DB 'Hello!’ ; 定义源串
aa ENDS
bb SEGMENT ;数据段 2
yy DB 6 dup (?) ; 定义目的缓冲区
bb ENDS
cc SEGMENT ;代码段
ASSUME CS:cc,DS:aa,ES:bb ;指示指令中标号,变量所在段
start,CLD ;设置传送方向
MOV AX,aa ;DS,SI ← 源串首地址
MOV DS,AX
LEA SI,xx
MOV AX,SEG yy ;ES,DI← 目的首地址
MOV ES,AX
MOV DI,OFFSET yy
MOV CX,6 ;CX ← 串的长度
REP MOVSB ;串传送
MOV AH,4CH ;调用 4CH系统功能,返回 DOS
INT 21H
cc ENDS
END ; start ;指示程序结束和程序入口
79
5,如下操作为何查看不到结果?
(实验课上讨论 )
D:\>MASM hello; ;汇编源程序
D:\>LINK hello; ;连接程序
D:\>hello ;先在 DOS下运行程序
D:\>DEBUG ;再进入 DEBUG查看结果
- D 129E:0 L30 ;查看目的串
129E:0000 2A 75 05 80 0E 2D DA 02-3A 06 14 D4 75 C9 4E 32 *u...-..:...u.N2
129E:0010 C0 86 04 46 3C 0D 75 02-88 04 89 36 EB D8 89 0E,..F<.u....6....
129E:0020 E9 D8 C3 BE CE DC 8B 4C-05 8B 74 09 E8 08 00 03,......L..t.....
-D 129D:0 L30 ;查看源串
129D:0000 75 04 FE 06 29 DA 3C 3F-75 05 80 0E 2D DA 02 3C u...).<?u...-..<
129D:0010 2A 75 05 80 0E 2D DA 02-3A 06 14 D4 75 C9 4E 32 *u...-..:...u.N2
129D:0020 C0 86 04 46 3C 0D 75 02-88 04 89 36 EB D8 89 0E,..F<.u....6....
80
data1 SEGMENT ;数据段 1,(可据需要设定,也可无 )
…… ;变量定义
data1 ENDS
data2 SEGMENT ;数据段 2 (可据需要设定,也可无 )
……
data2 ENDS
code SEGMENT ;程序段
ASSUME CS,code,DS:data1,ES:data2
start:,、,;程序主体部分
、、、
、、、
、、、
MOV AH,4CH ;返回 DOS
INT 21H
code ENDS
END start
完整汇编语言程序框架: